From 6b9b7b4b6848b18dc0b76ce5303563ec770c8e2f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:05 +0200 Subject: [PATCH 01/59] utils/Variant: use std::to_string() instead of std::ostringstream Signed-off-by: memeka --- xbmc/utils/Variant.cpp | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/xbmc/utils/Variant.cpp b/xbmc/utils/Variant.cpp index 17a117dc8ad4d..b86d9e05f7cf6 100644 --- a/xbmc/utils/Variant.cpp +++ b/xbmc/utils/Variant.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #ifndef strtoll @@ -506,18 +505,11 @@ std::string CVariant::asString(const std::string &fallback /* = "" */) const case VariantTypeBoolean: return m_data.boolean ? "true" : "false"; case VariantTypeInteger: + return std::to_string(m_data.integer); case VariantTypeUnsignedInteger: + return std::to_string(m_data.unsignedinteger); case VariantTypeDouble: - { - std::ostringstream strStream; - if (m_type == VariantTypeInteger) - strStream << m_data.integer; - else if (m_type == VariantTypeUnsignedInteger) - strStream << m_data.unsignedinteger; - else - strStream << m_data.dvalue; - return strStream.str(); - } + return std::to_string(m_data.dvalue); default: return fallback; } @@ -534,18 +526,11 @@ std::wstring CVariant::asWideString(const std::wstring &fallback /* = L"" */) co case VariantTypeBoolean: return m_data.boolean ? L"true" : L"false"; case VariantTypeInteger: + return std::to_wstring(m_data.integer); case VariantTypeUnsignedInteger: + return std::to_wstring(m_data.unsignedinteger); case VariantTypeDouble: - { - std::wostringstream strStream; - if (m_type == VariantTypeInteger) - strStream << m_data.integer; - else if (m_type == VariantTypeUnsignedInteger) - strStream << m_data.unsignedinteger; - else - strStream << m_data.dvalue; - return strStream.str(); - } + return std::to_wstring(m_data.dvalue); default: return fallback; } From 9ab180be03ebf9d39a9e6f200b69fdd24fbd4cbd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:05 +0200 Subject: [PATCH 02/59] VideoPlayer: add "override" Remove redundant "virtual" keywords. Signed-off-by: memeka --- xbmc/cores/VideoPlayer/VideoPlayer.h | 140 +++++++++++++-------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.h b/xbmc/cores/VideoPlayer/VideoPlayer.h index da02d907f5e4e..d18fe3d1bfae7 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.h +++ b/xbmc/cores/VideoPlayer/VideoPlayer.h @@ -293,118 +293,118 @@ class CVideoPlayer : public IPlayer, public CThread, public IVideoPlayer, public public: CVideoPlayer(IPlayerCallback& callback); virtual ~CVideoPlayer(); - virtual bool OpenFile(const CFileItem& file, const CPlayerOptions &options); - virtual bool CloseFile(bool reopen = false); - virtual bool IsPlaying() const; + bool OpenFile(const CFileItem& file, const CPlayerOptions &options) override; + bool CloseFile(bool reopen = false) override; + bool IsPlaying() const override; virtual void Pause() override; - virtual bool HasVideo() const; - virtual bool HasAudio() const; - virtual bool HasRDS() const; - virtual bool IsPassthrough() const; - virtual bool CanSeek(); - virtual void Seek(bool bPlus, bool bLargeStep, bool bChapterOverride); - virtual bool SeekScene(bool bPlus = true); - virtual void SeekPercentage(float iPercent); - virtual float GetPercentage(); - virtual float GetCachePercentage(); + bool HasVideo() const override; + bool HasAudio() const override; + bool HasRDS() const override; + bool IsPassthrough() const override; + bool CanSeek() override; + void Seek(bool bPlus, bool bLargeStep, bool bChapterOverride) override; + bool SeekScene(bool bPlus = true) override; + void SeekPercentage(float iPercent) override; + float GetPercentage() override; + float GetCachePercentage() override; virtual void SetVolume(float nVolume) override; virtual void SetMute(bool bOnOff) override; virtual void SetDynamicRangeCompression(long drc) override; - virtual bool CanRecord(); - virtual bool IsRecording(); - virtual bool CanPause(); - virtual bool Record(bool bOnOff); - virtual void SetAVDelay(float fValue = 0.0f); - virtual float GetAVDelay(); + bool CanRecord() override; + bool IsRecording() override; + bool CanPause() override; + bool Record(bool bOnOff) override; + void SetAVDelay(float fValue = 0.0f) override; + float GetAVDelay() override; virtual bool IsInMenu() const override; virtual bool HasMenu() const override; - virtual void SetSubTitleDelay(float fValue = 0.0f); - virtual float GetSubTitleDelay(); - virtual int GetSubtitleCount(); - virtual int GetSubtitle(); - virtual void GetSubtitleStreamInfo(int index, SPlayerSubtitleStreamInfo &info); - virtual void SetSubtitle(int iStream); - virtual bool GetSubtitleVisible(); - virtual void SetSubtitleVisible(bool bVisible); - virtual void AddSubtitle(const std::string& strSubPath); + void SetSubTitleDelay(float fValue = 0.0f) override; + float GetSubTitleDelay() override; + int GetSubtitleCount() override; + int GetSubtitle() override; + void GetSubtitleStreamInfo(int index, SPlayerSubtitleStreamInfo &info) override; + void SetSubtitle(int iStream) override; + bool GetSubtitleVisible() override; + void SetSubtitleVisible(bool bVisible) override; + void AddSubtitle(const std::string& strSubPath) override; - virtual int GetAudioStreamCount(); - virtual int GetAudioStream(); - virtual void SetAudioStream(int iStream); + int GetAudioStreamCount() override; + int GetAudioStream() override; + void SetAudioStream(int iStream) override; virtual int GetVideoStream() const override; virtual int GetVideoStreamCount() const override; virtual void GetVideoStreamInfo(int streamId, SPlayerVideoStreamInfo &info) override; - virtual void SetVideoStream(int iStream); + void SetVideoStream(int iStream) override; - virtual TextCacheStruct_t* GetTeletextCache(); - virtual void LoadPage(int p, int sp, unsigned char* buffer); + TextCacheStruct_t* GetTeletextCache() override; + void LoadPage(int p, int sp, unsigned char* buffer) override; - virtual std::string GetRadioText(unsigned int line); + std::string GetRadioText(unsigned int line) override; - virtual int GetChapterCount(); - virtual int GetChapter(); - virtual void GetChapterName(std::string& strChapterName, int chapterIdx=-1); - virtual int64_t GetChapterPos(int chapterIdx=-1); - virtual int SeekChapter(int iChapter); + int GetChapterCount() override; + int GetChapter() override; + void GetChapterName(std::string& strChapterName, int chapterIdx=-1) override; + int64_t GetChapterPos(int chapterIdx=-1) override; + int SeekChapter(int iChapter) override; - virtual void SeekTime(int64_t iTime); - virtual bool SeekTimeRelative(int64_t iTime); - virtual int64_t GetTime(); - virtual int64_t GetTotalTime(); + void SeekTime(int64_t iTime) override; + bool SeekTimeRelative(int64_t iTime) override; + int64_t GetTime() override; + int64_t GetTotalTime() override; virtual void SetSpeed(float speed) override; virtual float GetSpeed() override; virtual bool SupportsTempo() override; - virtual bool OnAction(const CAction &action); + bool OnAction(const CAction &action) override; - virtual int GetSourceBitrate(); - virtual bool GetStreamDetails(CStreamDetails &details); - virtual void GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info); + int GetSourceBitrate() override; + bool GetStreamDetails(CStreamDetails &details) override; + void GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info) override; - virtual std::string GetPlayerState(); - virtual bool SetPlayerState(const std::string& state); + std::string GetPlayerState() override; + bool SetPlayerState(const std::string& state) override; - virtual std::string GetPlayingTitle(); + std::string GetPlayingTitle() override; - virtual bool SwitchChannel(const PVR::CPVRChannelPtr &channel); + bool SwitchChannel(const PVR::CPVRChannelPtr &channel) override; - virtual void FrameMove(); - virtual void Render(bool clear, uint32_t alpha = 255, bool gui = true); - virtual void FlushRenderer(); - virtual void SetRenderViewMode(int mode); + void FrameMove() override; + void Render(bool clear, uint32_t alpha = 255, bool gui = true) override; + void FlushRenderer() override; + void SetRenderViewMode(int mode) override; float GetRenderAspectRatio(); - virtual void TriggerUpdateResolution(); - virtual bool IsRenderingVideo(); - virtual bool IsRenderingGuiLayer(); - virtual bool IsRenderingVideoLayer(); + void TriggerUpdateResolution() override; + bool IsRenderingVideo() override; + bool IsRenderingGuiLayer() override; + bool IsRenderingVideoLayer() override; virtual bool Supports(EINTERLACEMETHOD method) override; virtual EINTERLACEMETHOD GetDeinterlacingMethodDefault() override; virtual bool Supports(ESCALINGMETHOD method) override; virtual bool Supports(ERENDERFEATURE feature) override; - virtual unsigned int RenderCaptureAlloc(); - virtual void RenderCapture(unsigned int captureId, unsigned int width, unsigned int height, int flags); - virtual void RenderCaptureRelease(unsigned int captureId); - virtual bool RenderCaptureGetPixels(unsigned int captureId, unsigned int millis, uint8_t *buffer, unsigned int size); + unsigned int RenderCaptureAlloc() override; + void RenderCapture(unsigned int captureId, unsigned int width, unsigned int height, int flags) override; + void RenderCaptureRelease(unsigned int captureId) override; + bool RenderCaptureGetPixels(unsigned int captureId, unsigned int millis, uint8_t *buffer, unsigned int size) override; // IDispResource interface - virtual void OnLostDisplay(); - virtual void OnResetDisplay(); + void OnLostDisplay() override; + void OnResetDisplay() override; virtual bool IsCaching() const override; virtual int GetCacheLevel() const override; - virtual int OnDVDNavResult(void* pData, int iMessage) override; + int OnDVDNavResult(void* pData, int iMessage) override; void GetVideoResolution(unsigned int &width, unsigned int &height) override; protected: friend class CSelectionStreams; - virtual void OnStartup(); - virtual void OnExit(); - virtual void Process(); + virtual void OnStartup() override; + virtual void OnExit() override; + virtual void Process() override; virtual void VideoParamsChange() override; virtual void GetDebugInfo(std::string &audio, std::string &video, std::string &general) override; virtual void UpdateClockSync(bool enabled) override; From 097e65e8a2bbe0911a285b0ff8fdd3b15399c8a3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:05 +0200 Subject: [PATCH 03/59] xbmc/gen-compileinfo.mk: set GIT_DIR, fixes out-of-tree build Signed-off-by: memeka --- xbmc/gen-compileinfo.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/gen-compileinfo.mk b/xbmc/gen-compileinfo.mk index 11ded2a142024..4d93bdde58ee4 100644 --- a/xbmc/gen-compileinfo.mk +++ b/xbmc/gen-compileinfo.mk @@ -13,6 +13,7 @@ $(FILEPATH)/.GitRevision: @if test -f $(GITVERFILE); then \ GITREV=$$(cat $(GITVERFILE)) ;\ elif test "$(GIT)" = "git" && test -d $(FILEPATH)/../.git ; then \ + export GIT_DIR="$(FILEPATH)/../.git"; \ if ! git diff-files --ignore-submodules --quiet -- || ! git diff-index --cached --ignore-submodules --quiet HEAD --; then \ BUILD_DATE=$$(date -u "+%F"); \ BUILD_SCMID=$$(git --no-pager log --abbrev=7 -n 1 --pretty=format:"%h-dirty"); \ From d796b28dc9fdabcc6bcc49d8acfe0d65be2019a2 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:05 +0200 Subject: [PATCH 04/59] xbmc/gen-compileinfo.mk: use $(FILEPATH) for all paths, fixes out-of-tree build Signed-off-by: memeka --- xbmc/gen-compileinfo.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbmc/gen-compileinfo.mk b/xbmc/gen-compileinfo.mk index 4d93bdde58ee4..f148d702917c8 100644 --- a/xbmc/gen-compileinfo.mk +++ b/xbmc/gen-compileinfo.mk @@ -6,8 +6,8 @@ GITVERFILE := ../VERSION GIT = $(notdir $(shell which git)) .PHONY: GitRevision $(FILEPATH)/.GitRevision -all: $(FILEPATH)/CompileInfo.cpp GitRevision -GitRevision: $(FILEPATH)/.GitRevision +all: $(FILEPATH)/CompileInfo.cpp $(FILEPATH)/GitRevision +$(FILEPATH)/GitRevision: $(FILEPATH)/.GitRevision $(FILEPATH)/.GitRevision: @if test -f $(GITVERFILE); then \ From b3a8e26f2fc84968a2b2681ab193fef6ee92aaf3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:05 +0200 Subject: [PATCH 05/59] JsonSchemaBuilder/Makefile: remove unused variable APPBIN Signed-off-by: memeka --- tools/depends/native/JsonSchemaBuilder/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/depends/native/JsonSchemaBuilder/Makefile b/tools/depends/native/JsonSchemaBuilder/Makefile index cf5d20b055a23..77d7c3fd24d35 100644 --- a/tools/depends/native/JsonSchemaBuilder/Makefile +++ b/tools/depends/native/JsonSchemaBuilder/Makefile @@ -17,7 +17,6 @@ SOURCE=$(ROOT_DIR)/src CONFIGURE=./configure --prefix=$(PREFIX) APP=$(SOURCE)/JsonSchemaBuilder -APPBIN=$(PREFIX)/bin/JsonSchemaBuilder all: .installed-$(PLATFORM) From 9c83280a4f4ec1e169bd2436c9f055411df32adc Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:05 +0200 Subject: [PATCH 06/59] JsonSchemaBuilder/Makefile: fix the APP path The program gets installed to $(PREFIX)/bin, not to $(SOURCE). Signed-off-by: memeka --- tools/depends/native/JsonSchemaBuilder/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/depends/native/JsonSchemaBuilder/Makefile b/tools/depends/native/JsonSchemaBuilder/Makefile index 77d7c3fd24d35..f615d3b262083 100644 --- a/tools/depends/native/JsonSchemaBuilder/Makefile +++ b/tools/depends/native/JsonSchemaBuilder/Makefile @@ -16,7 +16,7 @@ endif SOURCE=$(ROOT_DIR)/src CONFIGURE=./configure --prefix=$(PREFIX) -APP=$(SOURCE)/JsonSchemaBuilder +APP=$(PREFIX)/bin/JsonSchemaBuilder all: .installed-$(PLATFORM) From 929dcfcb8a9bd94cdba1e59c3bbe4bdc9ea4ed0c Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:05 +0200 Subject: [PATCH 07/59] JsonSchemaBuilder/Makefile: simplify rm/mkdir/cp Signed-off-by: memeka --- tools/depends/native/JsonSchemaBuilder/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/depends/native/JsonSchemaBuilder/Makefile b/tools/depends/native/JsonSchemaBuilder/Makefile index f615d3b262083..876dae3bad823 100644 --- a/tools/depends/native/JsonSchemaBuilder/Makefile +++ b/tools/depends/native/JsonSchemaBuilder/Makefile @@ -21,8 +21,8 @@ APP=$(PREFIX)/bin/JsonSchemaBuilder all: .installed-$(PLATFORM) $(PLATFORM): - -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) - cd $(PLATFORM); cp -a $(SOURCE)/* . + rm -rf $(PLATFORM) + cp -a $(SOURCE) $(PLATFORM) cd $(PLATFORM); ./autogen.sh cd $(PLATFORM); $(CONFIGURE) From c59c5eb1569a28e70eb2e877eb80ef3e4ac74cb9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 08/59] JsonSchemaBuilder/Makefile: split the target, improve robustness Signed-off-by: memeka --- tools/depends/native/JsonSchemaBuilder/Makefile | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tools/depends/native/JsonSchemaBuilder/Makefile b/tools/depends/native/JsonSchemaBuilder/Makefile index 876dae3bad823..3951342b1c646 100644 --- a/tools/depends/native/JsonSchemaBuilder/Makefile +++ b/tools/depends/native/JsonSchemaBuilder/Makefile @@ -18,26 +18,27 @@ SOURCE=$(ROOT_DIR)/src CONFIGURE=./configure --prefix=$(PREFIX) APP=$(PREFIX)/bin/JsonSchemaBuilder -all: .installed-$(PLATFORM) +all: $(APP) -$(PLATFORM): +$(PLATFORM)/autogen.sh: $(SOURCE)/* rm -rf $(PLATFORM) cp -a $(SOURCE) $(PLATFORM) + +$(PLATFORM)/configure: $(PLATFORM)/autogen.sh cd $(PLATFORM); ./autogen.sh - cd $(PLATFORM); $(CONFIGURE) +$(PLATFORM)/config.log: $(PLATFORM)/configure + cd $(PLATFORM); $(CONFIGURE) -$(APP): $(PLATFORM) +$(PLATFORM)/JsonSchemaBuilder: $(PLATFORM)/config.log $(MAKE) -C $(PLATFORM) - -.installed-$(PLATFORM): $(APP) +$(APP): $(PLATFORM)/JsonSchemaBuilder $(MAKE) -C $(PLATFORM) install - touch $@ clean: $(MAKE) -C $(PLATFORM) clean distclean:: - rm -rf $(PLATFORM) .installed-$(PLATFORM) + rm -rf $(PLATFORM) -rm -rf bin From 5afcbe5643086b9d497541112a0d37766193d2a2 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 09/59] JsonSchemaBuilder/Makefile: check "cd" success Signed-off-by: memeka --- tools/depends/native/JsonSchemaBuilder/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/depends/native/JsonSchemaBuilder/Makefile b/tools/depends/native/JsonSchemaBuilder/Makefile index 3951342b1c646..3abd7293cc0c7 100644 --- a/tools/depends/native/JsonSchemaBuilder/Makefile +++ b/tools/depends/native/JsonSchemaBuilder/Makefile @@ -25,10 +25,10 @@ $(PLATFORM)/autogen.sh: $(SOURCE)/* cp -a $(SOURCE) $(PLATFORM) $(PLATFORM)/configure: $(PLATFORM)/autogen.sh - cd $(PLATFORM); ./autogen.sh + cd $(PLATFORM) && ./autogen.sh $(PLATFORM)/config.log: $(PLATFORM)/configure - cd $(PLATFORM); $(CONFIGURE) + cd $(PLATFORM) && $(CONFIGURE) $(PLATFORM)/JsonSchemaBuilder: $(PLATFORM)/config.log $(MAKE) -C $(PLATFORM) From 56d8b42483ef396a7fef4b4c6d6a0a8662b0fae3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 10/59] JsonSchemaBuilder/Makefile: build out-of-tree Don't need a copy of src/ for this. This was fragile anyway. Signed-off-by: memeka --- tools/depends/native/JsonSchemaBuilder/.gitignore | 5 +++++ tools/depends/native/JsonSchemaBuilder/Makefile | 14 ++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 tools/depends/native/JsonSchemaBuilder/.gitignore diff --git a/tools/depends/native/JsonSchemaBuilder/.gitignore b/tools/depends/native/JsonSchemaBuilder/.gitignore new file mode 100644 index 0000000000000..bbd8cbfa4d39e --- /dev/null +++ b/tools/depends/native/JsonSchemaBuilder/.gitignore @@ -0,0 +1,5 @@ +/src/Makefile.in +/src/aclocal.m4 +/src/*.cache +/src/config/ +/src/configure diff --git a/tools/depends/native/JsonSchemaBuilder/Makefile b/tools/depends/native/JsonSchemaBuilder/Makefile index 3abd7293cc0c7..4c87012e14884 100644 --- a/tools/depends/native/JsonSchemaBuilder/Makefile +++ b/tools/depends/native/JsonSchemaBuilder/Makefile @@ -15,19 +15,17 @@ endif SOURCE=$(ROOT_DIR)/src -CONFIGURE=./configure --prefix=$(PREFIX) +CONFIGURE=$(SOURCE)/configure --prefix=$(PREFIX) APP=$(PREFIX)/bin/JsonSchemaBuilder all: $(APP) -$(PLATFORM)/autogen.sh: $(SOURCE)/* - rm -rf $(PLATFORM) - cp -a $(SOURCE) $(PLATFORM) - -$(PLATFORM)/configure: $(PLATFORM)/autogen.sh - cd $(PLATFORM) && ./autogen.sh +$(SOURCE)/configure: $(SOURCE)/configure.ac + cd $(SOURCE) && ./autogen.sh -$(PLATFORM)/config.log: $(PLATFORM)/configure +$(PLATFORM)/config.log: $(SOURCE)/configure + rm -rf $(PLATFORM) + mkdir -p $(PLATFORM) cd $(PLATFORM) && $(CONFIGURE) $(PLATFORM)/JsonSchemaBuilder: $(PLATFORM)/config.log From 49962c464cd2482acd3654dde599f8e7ae7b86dc Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 11/59] guilib/GUIBaseContainer: use std::list for CGUIListItemLayout This reduces the overhead, because resizing the std::vector will create lots of temporary CGUIListItemLayout copies. A std::list never needs to move its items. Signed-off-by: memeka --- xbmc/guilib/GUIBaseContainer.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xbmc/guilib/GUIBaseContainer.h b/xbmc/guilib/GUIBaseContainer.h index 96d05650dd07a..4ee2afc64207e 100644 --- a/xbmc/guilib/GUIBaseContainer.h +++ b/xbmc/guilib/GUIBaseContainer.h @@ -32,6 +32,8 @@ #include "IGUIContainer.h" #include "utils/Stopwatch.h" +#include + /*! \ingroup controls \brief @@ -153,8 +155,8 @@ class CGUIBaseContainer : public IGUIContainer int m_pageControl; - std::vector m_layouts; - std::vector m_focusedLayouts; + std::list m_layouts; + std::list m_focusedLayouts; CGUIListItemLayout *m_layout; CGUIListItemLayout *m_focusedLayout; From 37579498d7cc5f1a6e05c1649a510e555497d84a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 12/59] Video/RenderManager: move protected #includes out of #if block Signed-off-by: memeka --- xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp index 420b5b5d8e608..07207ccb65647 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp @@ -34,15 +34,14 @@ #include "settings/MediaSettings.h" #include "settings/Settings.h" -#if defined(HAS_GL) #include "LinuxRendererGL.h" #include "HwDecRender/RendererVAAPI.h" #include "HwDecRender/RendererVDPAU.h" -#if defined(TARGET_DARWIN_OSX) #include "HwDecRender/RendererVTBGL.h" -#endif +#include "LinuxRendererGLES.h" + +#if defined(HAS_GL) #elif HAS_GLES == 2 - #include "LinuxRendererGLES.h" #if defined(HAS_MMAL) #include "HwDecRender/MMALRenderer.h" #endif From d4496676b3f6b215d30c082e30245d9e8414f6fa Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 13/59] Video/RendererVAAPI: allow building with GLES2 Signed-off-by: memeka --- .../VideoRenderers/HwDecRender/RendererVAAPI.cpp | 4 ++-- .../VideoRenderers/HwDecRender/RendererVAAPI.h | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.cpp index 0d196d002b4f9..3fd4953f4b182 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.cpp @@ -80,12 +80,12 @@ CRenderInfo CRendererVAAPI::GetRenderInfo() bool CRendererVAAPI::Supports(ERENDERFEATURE feature) { - return CLinuxRendererGL::Supports(feature); + return CRendererVAAPIBase::Supports(feature); } bool CRendererVAAPI::Supports(ESCALINGMETHOD method) { - return CLinuxRendererGL::Supports(method); + return CRendererVAAPIBase::Supports(method); } bool CRendererVAAPI::LoadShadersHook() diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.h index c2d46468f0885..de2126cf47bb6 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.h @@ -24,9 +24,16 @@ #ifdef HAVE_LIBVA +#ifdef HAS_GL #include "cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h" +using CRendererVAAPIBase = CLinuxRendererGL; +#else +#include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h" +using CRendererVAAPIBase = CLinuxRendererGLES; +#endif + -class CRendererVAAPI : public CLinuxRendererGL +class CRendererVAAPI : public CRendererVAAPIBase { public: CRendererVAAPI(); From a63e9956b94dcab0baf13e7b2299f3b297e36876 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 14/59] Video/CLinuxRendererGLES: UploadNV12Texture() returns bool Signed-off-by: memeka --- xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp | 6 +++--- xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp index f478fb0c02834..e9bdfba9ec65e 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp @@ -1376,14 +1376,14 @@ bool CLinuxRendererGLES::CreateYV12Texture(int index) //******************************************************************************************************** // NV12 Texture loading, creation and deletion //******************************************************************************************************** -void CLinuxRendererGLES::UploadNV12Texture(int source) +bool CLinuxRendererGLES::UploadNV12Texture(int source) { YUVBUFFER& buf = m_buffers[source]; YV12Image* im = &buf.image; YUVFIELDS& fields = buf.fields; if (!(im->flags & IMAGE_FLAG_READY)) - return; + return false; bool deinterlacing; if (m_currentField == FIELD_FULL) deinterlacing = false; @@ -1436,7 +1436,7 @@ void CLinuxRendererGLES::UploadNV12Texture(int source) CalculateTextureSourceRects(source, 3); glDisable(m_textureTarget); - return; + return true; } bool CLinuxRendererGLES::CreateNV12Texture(int index) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h index d54041d4cd8e7..67c3f84e00ca1 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h @@ -170,7 +170,7 @@ class CLinuxRendererGLES : public CBaseRenderer bool CreateYV12Texture(int index); virtual bool SkipUploadYV12(int index) { return false; } - void UploadNV12Texture(int index); + bool UploadNV12Texture(int index); void DeleteNV12Texture(int index); bool CreateNV12Texture(int index); From 8834b585d6e4af4931d2e0aeb11e8245fcc2973d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 15/59] Video/VAAPI: make compatible with GLES2 Signed-off-by: memeka --- xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp index 2f6502561de8a..bf7b710bcbc18 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp @@ -2375,12 +2375,14 @@ bool COutput::GLInit() } #endif +#ifdef HAS_GL if (!g_Windowing.IsExtSupported("GL_ARB_texture_non_power_of_two") && g_Windowing.IsExtSupported("GL_ARB_texture_rectangle")) { m_textureTarget = GL_TEXTURE_RECTANGLE_ARB; } else +#endif m_textureTarget = GL_TEXTURE_2D; eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); From a228439ccc419fb42eee98838150a9a932c7f1c6 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 16/59] Video/VAAPI: use 0 instead of None, which is a libX11 macro Signed-off-by: memeka --- xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp | 2 +- xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h | 4 ++-- .../VideoRenderers/HwDecRender/RendererVAAPI.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp index bf7b710bcbc18..51c7d2be85cdc 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp @@ -2346,7 +2346,7 @@ void COutput::ReleaseBufferPool(bool precleanup) if (pic->texture) { glDeleteTextures(1, &pic->texture); - pic->texture = None; + pic->texture = 0; } av_frame_free(&pic->avFrame); pic->valid = false; diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h index cbaf4a6d3f657..7f62cfe33eada 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h @@ -189,8 +189,8 @@ class CVaapiRenderPicture friend class COutput; public: CVaapiRenderPicture(CCriticalSection §ion) - : texWidth(0), texHeight(0), texture(None), textureY(None), textureVU(None), valid(false), vaapi(NULL), avFrame(NULL), - usefence(false), refCount(0), renderPicSection(section) { fence = None; } + : texWidth(0), texHeight(0), texture(0), textureY(0), textureVU(0), valid(false), vaapi(NULL), avFrame(NULL), + usefence(false), refCount(0), renderPicSection(section) { fence = 0; } void Sync(); DVDVideoPicture DVDPic; int texWidth, texHeight; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.cpp index 3fd4953f4b182..9140181b45074 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVAAPI.cpp @@ -139,9 +139,9 @@ void CRendererVAAPI::DeleteTexture(int index) m_buffers[index].hwDec = NULL; YUVFIELDS &fields = m_buffers[index].fields; - fields[FIELD_FULL][0].id = None; - fields[FIELD_FULL][1].id = None; - fields[FIELD_FULL][2].id = None; + fields[FIELD_FULL][0].id = 0; + fields[FIELD_FULL][1].id = 0; + fields[FIELD_FULL][2].id = 0; } bool CRendererVAAPI::UploadTexture(int index) From 30c0994317baacea89188c6c2d09e947ecfb270b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 17/59] shaders/yuv2rgb_basic_gles.glsl: support NV12_RRG format Fixes missing green channel when VA-API is used with GLES2. This switch was already present in OpenGL, but not in GLES2. Signed-off-by: memeka --- system/shaders/yuv2rgb_basic_gles.glsl | 7 +++++++ .../VideoRenderers/VideoShaders/YUV2RGBShader.cpp | 2 ++ 2 files changed, 9 insertions(+) diff --git a/system/shaders/yuv2rgb_basic_gles.glsl b/system/shaders/yuv2rgb_basic_gles.glsl index 07bae91e8b36c..82fa003b533ad 100644 --- a/system/shaders/yuv2rgb_basic_gles.glsl +++ b/system/shaders/yuv2rgb_basic_gles.glsl @@ -32,10 +32,17 @@ uniform mat4 m_yuvmat; void main() { vec4 yuv, rgb; +#if defined(XBMC_NV12_RRG) + yuv.rgba = vec4( texture2D(m_sampY, m_cordY).r + , texture2D(m_sampU, m_cordU).r + , texture2D(m_sampV, m_cordV).g + , 1.0); +#else yuv.rgba = vec4( texture2D(m_sampY, m_cordY).r , texture2D(m_sampU, m_cordU).g , texture2D(m_sampV, m_cordV).a , 1.0); +#endif rgb = m_yuvmat * yuv; rgb.a = m_alpha; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShader.cpp index 9cc3c424442fe..3e549aea1e11c 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShader.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShader.cpp @@ -245,6 +245,8 @@ BaseYUV2RGBGLSLShader::BaseYUV2RGBGLSLShader(bool rect, unsigned flags, ERenderF m_defines += "#define XBMC_NV12\n"; else if (m_format == RENDER_FMT_CVBREF) m_defines += "#define XBMC_YV12\n"; + else if (m_format == RENDER_FMT_VAAPI) + m_defines += "#define XBMC_NV12_RRG\n"; else CLog::Log(LOGERROR, "GL: BaseYUV2RGBGLSLShader - unsupported format %d", m_format); From e1cda86913e0ef9a0f35b4c09c72dd9ddc4614a9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 18/59] tools/depends/target/libdvdcss: generate empty ChangeLog to prevent "git log" call Signed-off-by: memeka --- tools/depends/target/libdvdcss/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/depends/target/libdvdcss/Makefile b/tools/depends/target/libdvdcss/Makefile index 518ce2b1019f5..cf7f5a4c7b62c 100644 --- a/tools/depends/target/libdvdcss/Makefile +++ b/tools/depends/target/libdvdcss/Makefile @@ -44,6 +44,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) cd $(PLATFORM); $(AUTORECONF) -vif && ac_cv_path_GIT= ./configure $(config) $(PLATFORM)/.libs/$(LIBNAME).a: $(PLATFORM) + [ -f $(PLATFORM)/ChangeLog ] || touch $(PLATFORM)/ChangeLog [ -d $(PLATFORM)/.libs ] && [ ! -f $@ ] && $(MAKE) -C $(PLATFORM) clean || : $(MAKE) -C $(PLATFORM) From 0f21082fe732c3f205af7dfd5b622105762a1314 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 19/59] lib/gtest: use only FUSED_GTEST_SRC for fused-gtest dependency Fix out-of-tree build due to VPATH breakage. Signed-off-by: memeka --- lib/gtest/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gtest/Makefile.am b/lib/gtest/Makefile.am index 9c96b42572ca9..3f565fd7132b0 100644 --- a/lib/gtest/Makefile.am +++ b/lib/gtest/Makefile.am @@ -273,7 +273,7 @@ test_fused_gtest_test_CPPFLAGS = -I"$(srcdir)/fused-src" # Build rules for putting fused Google Test files into the distribution # package. The user can also create those files by manually running # scripts/fuse_gtest_files.py. -$(test_fused_gtest_test_SOURCES): fused-gtest +$(FUSED_GTEST_SRC): fused-gtest fused-gtest: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \ $(GTEST_SRC) src/gtest-all.cc src/gtest_main.cc \ From b8b13ad11a7496cb80ea2ae38d148b397fd5a5ec Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 20/59] lib/gtest: move fused-src to $(builddir) Signed-off-by: memeka --- lib/gtest/Makefile.am | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/gtest/Makefile.am b/lib/gtest/Makefile.am index 3f565fd7132b0..886ba73d4339b 100644 --- a/lib/gtest/Makefile.am +++ b/lib/gtest/Makefile.am @@ -278,15 +278,15 @@ $(FUSED_GTEST_SRC): fused-gtest fused-gtest: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \ $(GTEST_SRC) src/gtest-all.cc src/gtest_main.cc \ scripts/fuse_gtest_files.py - mkdir -p "$(srcdir)/fused-src" - chmod -R u+w "$(srcdir)/fused-src" - rm -f "$(srcdir)/fused-src/gtest/gtest-all.cc" - rm -f "$(srcdir)/fused-src/gtest/gtest.h" - "$(srcdir)/scripts/fuse_gtest_files.py" "$(srcdir)/fused-src" - cp -f "$(srcdir)/src/gtest_main.cc" "$(srcdir)/fused-src/gtest/" + mkdir -p "$(builddir)/fused-src" + chmod -R u+w "$(builddir)/fused-src" + rm -f "$(builddir)/fused-src/gtest/gtest-all.cc" + rm -f "$(builddir)/fused-src/gtest/gtest.h" + "$(srcdir)/scripts/fuse_gtest_files.py" "$(builddir)/fused-src" + cp -f "$(srcdir)/src/gtest_main.cc" "$(builddir)/fused-src/gtest/" maintainer-clean-local: - rm -rf "$(srcdir)/fused-src" + rm -rf "$(builddir)/fused-src" endif # Death tests may produce core dumps in the build directory. In case From 2ab5a33ee9f8157f053dd8ba0a3ec3f4fb309fab Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 21/59] VideoPlayer: fix race condition in Get(StreamType) After Count() has been called, streams may be added or removed, leading to bogus results, because the mutex is released during the loop. Fix this by adding another recursive lock. Signed-off-by: memeka --- xbmc/cores/VideoPlayer/VideoPlayer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp index f909c8e451a05..fa05920f5b735 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp @@ -120,6 +120,7 @@ SelectionStream& CSelectionStreams::Get(StreamType type, int index) std::vector CSelectionStreams::Get(StreamType type) { + CSingleLock lock(m_section); std::vector streams; std::copy_if(m_Streams.begin(), m_Streams.end(), std::back_inserter(streams), [type](const SelectionStream &stream) From 22d61c5cd3d2b2bb6c51cb453c1ad2b458fda296 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 22/59] VideoPlayer: document that CSelectionStreams::Get() is thread-unsafe In https://github.com/xbmc/xbmc/pull/9442#discussion_r57427727, FernetMenta mandated that "this particular method does not require locking". It is important to document semantic API restrictions like this one. Signed-off-by: memeka --- xbmc/cores/VideoPlayer/VideoPlayer.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.h b/xbmc/cores/VideoPlayer/VideoPlayer.h index d18fe3d1bfae7..3695d9ae3e943 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.h +++ b/xbmc/cores/VideoPlayer/VideoPlayer.h @@ -271,7 +271,14 @@ class CSelectionStreams SelectionStream& Get (StreamType type, int index); bool Get (StreamType type, CDemuxStream::EFlags flag, SelectionStream& out); + /** + * Note: calling this method makes the whole instance thread-unsafe. + */ SelectionStreams Get(StreamType type); + + /** + * Note: calling this method makes the whole instance thread-unsafe. + */ template SelectionStreams Get(StreamType type, Compare compare) { SelectionStreams streams = Get(type); From 061590071639f9eba53f143dcd76c2e1c86052a6 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 23/59] ContextMenuManager: reserve space in CContextButtons Eliminate all but one std::vector reallocations. Signed-off-by: memeka --- xbmc/ContextMenuManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/ContextMenuManager.cpp b/xbmc/ContextMenuManager.cpp index 92688728be201..f334321660c1f 100644 --- a/xbmc/ContextMenuManager.cpp +++ b/xbmc/ContextMenuManager.cpp @@ -211,6 +211,7 @@ bool CONTEXTMENU::ShowFor(const CFileItemPtr& fileItem, const CContextMenuItem& return true; CContextButtons buttons; + buttons.reserve(menuItems.size()); for (size_t i = 0; i < menuItems.size(); ++i) buttons.Add(i, menuItems[i]->GetLabel(*fileItem)); From 8bbabb25a682991167a813df8055004cd0d40c28 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:06 +0200 Subject: [PATCH 24/59] Revert "[cleanup] wayland" This reverts commit cd814471012ed4f986c3905fc6c6eca754e7c50e. That commit deleted Wayland support completely without describing a reason. But I want to run Kodi on Wayland. Signed-off-by: memeka --- .gitignore | 4 + tools/depends/target/Makefile | 1 + xbmc/DllPaths_generated.h.in | 7 + xbmc/input/linux/XKBCommonKeymap.cpp | 387 +++++++++ xbmc/input/linux/XKBCommonKeymap.h | 78 ++ xbmc/windowing/DllWaylandClient.h | 193 +++++ xbmc/windowing/DllWaylandEgl.h | 65 ++ xbmc/windowing/DllXKBCommon.h | 92 ++ xbmc/windowing/WaylandProtocol.h | 244 ++++++ xbmc/windowing/WinEvents.cpp | 4 + xbmc/windowing/WinEventsWayland.cpp | 149 ++++ xbmc/windowing/WinEventsWayland.h | 65 ++ xbmc/windowing/egl/EGLNativeTypeWayland.cpp | 358 ++++++++ xbmc/windowing/egl/EGLNativeTypeWayland.h | 58 ++ xbmc/windowing/egl/EGLQuirks.h | 5 + xbmc/windowing/egl/EGLWrapper.cpp | 10 + xbmc/windowing/egl/EGLWrapper.h | 2 + xbmc/windowing/egl/WinSystemEGL.cpp | 17 +- xbmc/windowing/egl/wayland/Callback.cpp | 67 ++ xbmc/windowing/egl/wayland/Callback.h | 65 ++ xbmc/windowing/egl/wayland/Compositor.cpp | 75 ++ xbmc/windowing/egl/wayland/Compositor.h | 61 ++ xbmc/windowing/egl/wayland/Display.cpp | 116 +++ xbmc/windowing/egl/wayland/Display.h | 75 ++ xbmc/windowing/egl/wayland/OpenGLSurface.cpp | 64 ++ xbmc/windowing/egl/wayland/OpenGLSurface.h | 56 ++ xbmc/windowing/egl/wayland/Output.cpp | 255 ++++++ xbmc/windowing/egl/wayland/Output.h | 152 ++++ xbmc/windowing/egl/wayland/Region.cpp | 63 ++ xbmc/windowing/egl/wayland/Region.h | 54 ++ xbmc/windowing/egl/wayland/Registry.cpp | 156 ++++ xbmc/windowing/egl/wayland/Registry.h | 130 +++ xbmc/windowing/egl/wayland/Shell.cpp | 61 ++ xbmc/windowing/egl/wayland/Shell.h | 52 ++ xbmc/windowing/egl/wayland/ShellSurface.cpp | 116 +++ xbmc/windowing/egl/wayland/ShellSurface.h | 71 ++ xbmc/windowing/egl/wayland/Surface.cpp | 104 +++ xbmc/windowing/egl/wayland/Surface.h | 78 ++ .../egl/wayland/WaylandLibraries.cpp | 57 ++ xbmc/windowing/egl/wayland/WaylandLibraries.h | 84 ++ xbmc/windowing/egl/wayland/XBMCConnection.cpp | 763 +++++++++++++++++ xbmc/windowing/egl/wayland/XBMCConnection.h | 93 ++ xbmc/windowing/egl/wayland/XBMCSurface.cpp | 218 +++++ xbmc/windowing/egl/wayland/XBMCSurface.h | 74 ++ xbmc/windowing/tests/wayland/Makefile.in | 51 ++ .../tests/wayland/StubCursorManager.cpp | 28 + .../tests/wayland/StubCursorManager.h | 35 + .../tests/wayland/StubEventListener.cpp | 62 ++ .../tests/wayland/StubEventListener.h | 45 + .../wayland/TestEGLNativeTypeWayland.cpp | 277 ++++++ .../tests/wayland/TestWaylandInputUnit.cpp | 172 ++++ .../TestXBMCWaylandInputAcceptance.cpp | 581 +++++++++++++ xbmc/windowing/tests/wayland/TmpEnv.cpp | 38 + xbmc/windowing/tests/wayland/TmpEnv.h | 36 + .../windowing/tests/wayland/WestonProcess.cpp | 566 +++++++++++++ xbmc/windowing/tests/wayland/WestonProcess.h | 70 ++ xbmc/windowing/tests/wayland/WestonTest.cpp | 224 +++++ xbmc/windowing/tests/wayland/WestonTest.h | 50 ++ xbmc/windowing/tests/wayland/XBMCWayland.cpp | 128 +++ xbmc/windowing/tests/wayland/XBMCWayland.h | 78 ++ .../wayland/XBMCWaylandTestExtension.cpp | 792 ++++++++++++++++++ xbmc/windowing/tests/wayland/protocol.xml | 63 ++ xbmc/windowing/wayland/CursorManager.h | 38 + xbmc/windowing/wayland/EventListener.h | 40 + xbmc/windowing/wayland/EventLoop.cpp | 178 ++++ xbmc/windowing/wayland/EventLoop.h | 92 ++ xbmc/windowing/wayland/EventQueueStrategy.h | 45 + xbmc/windowing/wayland/InputFactory.cpp | 90 ++ xbmc/windowing/wayland/InputFactory.h | 82 ++ xbmc/windowing/wayland/Keyboard.cpp | 222 +++++ xbmc/windowing/wayland/Keyboard.h | 156 ++++ xbmc/windowing/wayland/KeyboardProcessor.cpp | 197 +++++ xbmc/windowing/wayland/KeyboardProcessor.h | 98 +++ xbmc/windowing/wayland/Pointer.cpp | 172 ++++ xbmc/windowing/wayland/Pointer.h | 130 +++ xbmc/windowing/wayland/PointerProcessor.cpp | 152 ++++ xbmc/windowing/wayland/PointerProcessor.h | 76 ++ xbmc/windowing/wayland/PollThread.cpp | 125 +++ xbmc/windowing/wayland/PollThread.h | 65 ++ xbmc/windowing/wayland/Seat.cpp | 112 +++ xbmc/windowing/wayland/Seat.h | 74 ++ xbmc/windowing/wayland/TimeoutManager.h | 45 + .../wayland/Wayland11EventQueueStrategy.cpp | 135 +++ .../wayland/Wayland11EventQueueStrategy.h | 79 ++ .../wayland/Wayland12EventQueueStrategy.cpp | 98 +++ .../wayland/Wayland12EventQueueStrategy.h | 59 ++ 86 files changed, 10750 insertions(+), 5 deletions(-) create mode 100644 xbmc/input/linux/XKBCommonKeymap.cpp create mode 100644 xbmc/input/linux/XKBCommonKeymap.h create mode 100644 xbmc/windowing/DllWaylandClient.h create mode 100644 xbmc/windowing/DllWaylandEgl.h create mode 100644 xbmc/windowing/DllXKBCommon.h create mode 100644 xbmc/windowing/WaylandProtocol.h create mode 100644 xbmc/windowing/WinEventsWayland.cpp create mode 100644 xbmc/windowing/WinEventsWayland.h create mode 100644 xbmc/windowing/egl/EGLNativeTypeWayland.cpp create mode 100644 xbmc/windowing/egl/EGLNativeTypeWayland.h create mode 100644 xbmc/windowing/egl/wayland/Callback.cpp create mode 100644 xbmc/windowing/egl/wayland/Callback.h create mode 100644 xbmc/windowing/egl/wayland/Compositor.cpp create mode 100644 xbmc/windowing/egl/wayland/Compositor.h create mode 100644 xbmc/windowing/egl/wayland/Display.cpp create mode 100644 xbmc/windowing/egl/wayland/Display.h create mode 100644 xbmc/windowing/egl/wayland/OpenGLSurface.cpp create mode 100644 xbmc/windowing/egl/wayland/OpenGLSurface.h create mode 100644 xbmc/windowing/egl/wayland/Output.cpp create mode 100644 xbmc/windowing/egl/wayland/Output.h create mode 100644 xbmc/windowing/egl/wayland/Region.cpp create mode 100644 xbmc/windowing/egl/wayland/Region.h create mode 100644 xbmc/windowing/egl/wayland/Registry.cpp create mode 100644 xbmc/windowing/egl/wayland/Registry.h create mode 100644 xbmc/windowing/egl/wayland/Shell.cpp create mode 100644 xbmc/windowing/egl/wayland/Shell.h create mode 100644 xbmc/windowing/egl/wayland/ShellSurface.cpp create mode 100644 xbmc/windowing/egl/wayland/ShellSurface.h create mode 100644 xbmc/windowing/egl/wayland/Surface.cpp create mode 100644 xbmc/windowing/egl/wayland/Surface.h create mode 100644 xbmc/windowing/egl/wayland/WaylandLibraries.cpp create mode 100644 xbmc/windowing/egl/wayland/WaylandLibraries.h create mode 100644 xbmc/windowing/egl/wayland/XBMCConnection.cpp create mode 100644 xbmc/windowing/egl/wayland/XBMCConnection.h create mode 100644 xbmc/windowing/egl/wayland/XBMCSurface.cpp create mode 100644 xbmc/windowing/egl/wayland/XBMCSurface.h create mode 100644 xbmc/windowing/tests/wayland/Makefile.in create mode 100644 xbmc/windowing/tests/wayland/StubCursorManager.cpp create mode 100644 xbmc/windowing/tests/wayland/StubCursorManager.h create mode 100644 xbmc/windowing/tests/wayland/StubEventListener.cpp create mode 100644 xbmc/windowing/tests/wayland/StubEventListener.h create mode 100644 xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp create mode 100644 xbmc/windowing/tests/wayland/TestWaylandInputUnit.cpp create mode 100644 xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp create mode 100644 xbmc/windowing/tests/wayland/TmpEnv.cpp create mode 100644 xbmc/windowing/tests/wayland/TmpEnv.h create mode 100644 xbmc/windowing/tests/wayland/WestonProcess.cpp create mode 100644 xbmc/windowing/tests/wayland/WestonProcess.h create mode 100644 xbmc/windowing/tests/wayland/WestonTest.cpp create mode 100644 xbmc/windowing/tests/wayland/WestonTest.h create mode 100644 xbmc/windowing/tests/wayland/XBMCWayland.cpp create mode 100644 xbmc/windowing/tests/wayland/XBMCWayland.h create mode 100644 xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp create mode 100644 xbmc/windowing/tests/wayland/protocol.xml create mode 100644 xbmc/windowing/wayland/CursorManager.h create mode 100644 xbmc/windowing/wayland/EventListener.h create mode 100644 xbmc/windowing/wayland/EventLoop.cpp create mode 100644 xbmc/windowing/wayland/EventLoop.h create mode 100644 xbmc/windowing/wayland/EventQueueStrategy.h create mode 100644 xbmc/windowing/wayland/InputFactory.cpp create mode 100644 xbmc/windowing/wayland/InputFactory.h create mode 100644 xbmc/windowing/wayland/Keyboard.cpp create mode 100644 xbmc/windowing/wayland/Keyboard.h create mode 100644 xbmc/windowing/wayland/KeyboardProcessor.cpp create mode 100644 xbmc/windowing/wayland/KeyboardProcessor.h create mode 100644 xbmc/windowing/wayland/Pointer.cpp create mode 100644 xbmc/windowing/wayland/Pointer.h create mode 100644 xbmc/windowing/wayland/PointerProcessor.cpp create mode 100644 xbmc/windowing/wayland/PointerProcessor.h create mode 100644 xbmc/windowing/wayland/PollThread.cpp create mode 100644 xbmc/windowing/wayland/PollThread.h create mode 100644 xbmc/windowing/wayland/Seat.cpp create mode 100644 xbmc/windowing/wayland/Seat.h create mode 100644 xbmc/windowing/wayland/TimeoutManager.h create mode 100644 xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp create mode 100644 xbmc/windowing/wayland/Wayland11EventQueueStrategy.h create mode 100644 xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp create mode 100644 xbmc/windowing/wayland/Wayland12EventQueueStrategy.h diff --git a/.gitignore b/.gitignore index c0631de7736bf..ff3f81fdc56e6 100644 --- a/.gitignore +++ b/.gitignore @@ -511,6 +511,10 @@ lib/cpluff/stamp-h1 # /xbmc/windowing/ /xbmc/windowing/Makefile /xbmc/windowing/egl/Makefile +/xbmc/windowing/tests/wayland/xbmc_wayland_test_client_protocol.h +/xbmc/windowing/tests/wayland/xbmc_wayland_test_protocol.c +/xbmc/windowing/tests/wayland/xbmc_wayland_test_server_protocol.h +/xbmc/windowing/tests/wayland/Makefile # /lib/libdvd/ /lib/libdvd/bin diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile index f0f0bf4f26484..fd524c12ec624 100644 --- a/tools/depends/target/Makefile +++ b/tools/depends/target/Makefile @@ -133,6 +133,7 @@ linux-system-libs-egl: [ -f $(PREFIX)/lib/pkgconfig/egl.pc ] || ln -sf /usr/lib/$(HOST)/pkgconfig/egl.pc $(PREFIX)/lib/pkgconfig/egl.pc [ -f $(PREFIX)/lib/pkgconfig/damageproto.pc ] || ln -sf /usr/share/pkgconfig/damageproto.pc $(PREFIX)/lib/pkgconfig/damageproto.pc [ -f $(PREFIX)/lib/pkgconfig/fixesproto.pc ] || ln -sf /usr/share/pkgconfig/fixesproto.pc $(PREFIX)/lib/pkgconfig/fixesproto.pc + [ -f $(PREFIX)/lib/pkgconfig/wayland-egl.pc ] || ln -sf /usr/share/pkgconfig/wayland-egl.pc $(PREFIX)/lib/pkgconfig/wayland-egl.pc [ -f $(PREFIX)/lib/pkgconfig/x11-xcb.pc ] || ln -sf /usr/lib/$(HOST)/pkgconfig/x11-xcb.pc $(PREFIX)/lib/pkgconfig/x11-xcb.pc [ -f $(PREFIX)/lib/pkgconfig/xcb-dri2.pc ] || ln -sf /usr/lib/$(HOST)/pkgconfig/xcb-dri2.pc $(PREFIX)/lib/pkgconfig/xcb-dri2.pc [ -f $(PREFIX)/lib/pkgconfig/xcb-dri3.pc ] || ln -sf /usr/lib/$(HOST)/pkgconfig/xcb-dri3.pc $(PREFIX)/lib/pkgconfig/xcb-dri3.pc diff --git a/xbmc/DllPaths_generated.h.in b/xbmc/DllPaths_generated.h.in index a4d45307034eb..76d6f3548fc47 100644 --- a/xbmc/DllPaths_generated.h.in +++ b/xbmc/DllPaths_generated.h.in @@ -46,6 +46,13 @@ /* libbluray */ #define DLL_PATH_LIBBLURAY "@BLURAY_SONAME@" +/* wayland */ +#define DLL_PATH_WAYLAND_CLIENT "@WAYLAND_CLIENT_LIBRARY_SONAME@" +#define DLL_PATH_WAYLAND_EGL "@WAYLAND_EGL_LIBRARY_SONAME@" + +/* xkbcommon */ +#define DLL_PATH_XKBCOMMON "@XKBCOMMON_LIBRARY_SONAME@" + /* sse4 */ #define DLL_PATH_LIBSSE4 "special://xbmcbin/system/libsse4-@ARCH@.so" diff --git a/xbmc/input/linux/XKBCommonKeymap.cpp b/xbmc/input/linux/XKBCommonKeymap.cpp new file mode 100644 index 0000000000000..acadf9f0261c6 --- /dev/null +++ b/xbmc/input/linux/XKBCommonKeymap.cpp @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include + +#include + +#include + +#include "Application.h" + +#include "windowing/DllXKBCommon.h" +#include "XKBCommonKeymap.h" +#include "Util.h" + +struct xkb_context * +CXKBKeymap::CreateXKBContext(IDllXKBCommon &xkbCommonLibrary) +{ + enum xkb_context_flags flags = + static_cast(0); + + struct xkb_context *context = xkbCommonLibrary.xkb_context_new(flags); + + /* It is the object who wants to create an XKBKeymap and not + * XKBKeymap itself that owns the xkb_context. The + * xkb_context is merely just a detail for construction of the + * more interesting xkb_state and xkb_keymap objects. + * + * Failure to create the context effectively means that that object + * will be unable to create a keymap or serve any useful purpose in + * processing key events. As such, it makes this an incomplete + * object and a runtime_error will be thrown */ + if (!context) + throw std::runtime_error("Failed to create xkb context"); + + return context; +} + +/* Opens a shared memory region and parses the data in it to an + * xkbcommon keymap. + * + * Generally a keymap is determined by the compositor by evaluating + * the currently available hardware and compiling a keymap + * most appropriate for that hardware. The compositor simply + * sends keycodes and modifier bits in the wire protocol. It is the + * client's responsibility to handle transformation of those hardware + * specific keycodes and modifier bits into a common keyboard + * representation. The compositor provides a serialized keymap + * in shared memory to allow clients to perform these transformations. + * + * This function does not own the file descriptor. The fact that it + * is sent as a const & is a reminder of that. It must not be closed + * from this function. + */ +struct xkb_keymap * +CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(IDllXKBCommon &xkbCommonLibrary, struct xkb_context *context, const int &fd, uint32_t size) +{ + const char *keymapString = static_cast(mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)); + if (keymapString == MAP_FAILED) + { + std::stringstream ss; + ss << "mmap: " << strerror(errno); + throw std::runtime_error(ss.str()); + } + + /* In every exit path, the keymap string memory region must be + * unmapped */ + BOOST_SCOPE_EXIT((keymapString)(size)) + { + munmap(const_cast(static_cast(keymapString)), + size); + } BOOST_SCOPE_EXIT_END + + enum xkb_keymap_compile_flags flags = + static_cast(0); + struct xkb_keymap *keymap = + xkbCommonLibrary.xkb_keymap_new_from_string(context, keymapString, XKB_KEYMAP_FORMAT_TEXT_V1, flags); + + /* Failure to compile a keymap is a runtime error and the caller + * should handle it */ + if (!keymap) + throw std::runtime_error("Failed to compile keymap"); + + return keymap; +} + +struct xkb_keymap * +CXKBKeymap::CreateXKBKeymapFromNames(IDllXKBCommon &xkbCommonLibrary, struct xkb_context *context, const std::string &rules, const std::string &model, const std::string &layout, const std::string &variant, const std::string &options) +{ + enum xkb_keymap_compile_flags flags = + static_cast(0); + + struct xkb_rule_names names = + { + rules.c_str(), + model.c_str(), + layout.c_str(), + variant.c_str(), + options.c_str() + }; + + struct xkb_keymap *keymap = + xkbCommonLibrary.xkb_keymap_new_from_names(context, &names, flags); + + if (!keymap) + throw std::runtime_error("Failed to compile keymap"); + + return keymap; +} + +struct xkb_state * +CXKBKeymap::CreateXKBStateFromKeymap(IDllXKBCommon &xkbCommonLibrary, struct xkb_keymap *keymap) +{ + struct xkb_state *state = xkbCommonLibrary.xkb_state_new(keymap); + + if (!state) + throw std::runtime_error("Failed to create keyboard state"); + + return state; +} + +/* A wrapper class around an xkbcommon keymap and state tracker. + * + * This class knows about some common modifier combinations and keeps + * track of the currently pressed keys and modifiers. It also has + * some utility functions to transform hardware keycodes into + * a common representation. + * + * Since this class is keeping track of all the pressed and depressed + * modifiers, IT MUST ALWAYS BE KEPT UP TO DATE WITH ANY NEWLY + * PRESSED MODIFIERS. Undefined behaviour will result if it is not + * kept up to date. + */ +CXKBKeymap::CXKBKeymap(IDllXKBCommon &xkbCommonLibrary, + struct xkb_keymap *keymap) : + m_xkbCommonLibrary(xkbCommonLibrary), + m_keymap(keymap), + m_state(CreateXKBStateFromKeymap(xkbCommonLibrary, + keymap)), + m_internalLeftControlIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + XKB_MOD_NAME_CTRL)), + m_internalLeftShiftIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + XKB_MOD_NAME_SHIFT)), + m_internalLeftSuperIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + XKB_MOD_NAME_LOGO)), + m_internalLeftAltIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + XKB_MOD_NAME_ALT)), + m_internalLeftMetaIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + "Meta")), + m_internalRightControlIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + "RControl")), + m_internalRightShiftIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + "RShift")), + m_internalRightSuperIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + "Hyper")), + m_internalRightAltIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + "AltGr")), + m_internalRightMetaIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + "Meta")), + m_internalCapsLockIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + XKB_LED_NAME_CAPS)), + m_internalNumLockIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + XKB_LED_NAME_NUM)), + m_internalModeIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, + XKB_LED_NAME_SCROLL)) +{ +} + +CXKBKeymap::~CXKBKeymap() +{ + m_xkbCommonLibrary.xkb_state_unref(m_state); + m_xkbCommonLibrary.xkb_keymap_unref(m_keymap); +} + +uint32_t +CXKBKeymap::KeysymForKeycode(uint32_t code) const +{ + const xkb_keysym_t *syms; + uint32_t numSyms; + + /* Key the keysyms for a particular keycode. Generally each + * keycode should only have one symbol, but if it has more than + * one then we're unable to just get one symbol for it, so that's + * a runtime_error which the client needs to handle. + * + * Codes sent generally have an offset of 8 */ + numSyms = m_xkbCommonLibrary.xkb_state_key_get_syms(m_state, code + 8, &syms); + + if (numSyms == 1) + return static_cast(syms[0]); + + std::stringstream ss; + ss << "Pressed key " + << std::hex + << code + << std::dec + << " is unspported"; + + throw std::runtime_error(ss.str()); +} + +/* Gets the currently depressed, latched and locked modifiers + * for the keyboard */ +uint32_t CXKBKeymap::CurrentModifiers() const +{ + enum xkb_state_component components = + static_cast (XKB_STATE_DEPRESSED | + XKB_STATE_LATCHED | + XKB_STATE_LOCKED); + xkb_mod_mask_t mask = m_xkbCommonLibrary.xkb_state_serialize_mods(m_state, + components); + return mask; +} + +/* Updates the currently depressed, latched, locked and group + * modifiers for a keyboard being tracked. + * + * THIS FUNCTION MUST BE CALLED WHENEVER MODIFIERS CHANGE */ +void CXKBKeymap::UpdateMask(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) +{ + m_xkbCommonLibrary.xkb_state_update_mask(m_state, depressed, latched, locked, 0, 0, group); +} + +uint32_t CXKBKeymap::ActiveXBMCModifiers() const +{ + xkb_mod_mask_t mask(CurrentModifiers()); + XBMCMod xbmcModifiers = XBMCKMOD_NONE; + + struct ModTable + { + xkb_mod_index_t xkbMod; + XBMCMod xbmcMod; + } modTable[] = + { + { m_internalLeftShiftIndex, XBMCKMOD_LSHIFT }, + { m_internalRightShiftIndex, XBMCKMOD_RSHIFT }, + { m_internalLeftShiftIndex, XBMCKMOD_LSUPER }, + { m_internalRightSuperIndex, XBMCKMOD_RSUPER }, + { m_internalLeftControlIndex, XBMCKMOD_LCTRL }, + { m_internalRightControlIndex, XBMCKMOD_RCTRL }, + { m_internalLeftAltIndex, XBMCKMOD_LALT }, + { m_internalRightAltIndex, XBMCKMOD_RALT }, + { m_internalLeftMetaIndex, XBMCKMOD_LMETA }, + { m_internalRightMetaIndex, XBMCKMOD_RMETA }, + { m_internalNumLockIndex, XBMCKMOD_NUM }, + { m_internalCapsLockIndex, XBMCKMOD_CAPS }, + { m_internalModeIndex, XBMCKMOD_MODE } + }; + + size_t modTableSize = ARRAY_SIZE(modTable); + + for (size_t i = 0; i < modTableSize; ++i) + { + if (mask & (1 << modTable[i].xkbMod)) + xbmcModifiers = static_cast(xbmcModifiers | modTable[i].xbmcMod); + } + + return static_cast(xbmcModifiers); +} + +uint32_t CXKBKeymap::XBMCKeysymForKeycode(uint32_t code) const +{ + uint32_t sym = KeysymForKeycode(code); + + /* Strip high bits from functional keys */ + if ((sym & ~(0xff00)) <= 0x1b) + sym = sym & ~(0xff00); + else if ((sym & ~(0xff00)) == 0xff) + sym = static_cast(XBMCK_DELETE); + + /* We only support keys within certain ranges */ + const bool isNavigationKey = (sym >= 0xff50 && sym <= 0xff58); + const bool isModifierKey = (sym >= 0xffe1 && sym <= 0xffee); + const bool isKeyPadKey = (sym >= 0xffb1 && sym <= 0xffb9); + const bool isFKey = (sym >= 0xffbe && sym <= 0xffcc); + const bool isMediaKey = (sym >= 0x1008ff26 && sym <= 0x1008ffa2); + + if (isNavigationKey || + isModifierKey || + isKeyPadKey || + isFKey || + isMediaKey) + { + /* Navigation keys are not in line, so we need to + * look them up */ + static const struct NavigationKeySyms + { + uint32_t xkb; + XBMCKey xbmc; + } navigationKeySyms[] = + { + { XKB_KEY_Home, XBMCK_HOME }, + { XKB_KEY_Left, XBMCK_LEFT }, + { XKB_KEY_Right, XBMCK_RIGHT }, + { XKB_KEY_Down, XBMCK_DOWN }, + { XKB_KEY_Up, XBMCK_UP }, + { XKB_KEY_Page_Up, XBMCK_PAGEUP }, + { XKB_KEY_Page_Down, XBMCK_PAGEDOWN }, + { XKB_KEY_End, XBMCK_END }, + { XKB_KEY_Insert, XBMCK_INSERT }, + { XKB_KEY_KP_0, XBMCK_KP0 }, + { XKB_KEY_KP_1, XBMCK_KP1 }, + { XKB_KEY_KP_2, XBMCK_KP2 }, + { XKB_KEY_KP_3, XBMCK_KP3 }, + { XKB_KEY_KP_4, XBMCK_KP4 }, + { XKB_KEY_KP_5, XBMCK_KP5 }, + { XKB_KEY_KP_6, XBMCK_KP6 }, + { XKB_KEY_KP_7, XBMCK_KP7 }, + { XKB_KEY_KP_8, XBMCK_KP8 }, + { XKB_KEY_KP_9, XBMCK_KP9 }, + { XKB_KEY_KP_Decimal, XBMCK_KP_PERIOD }, + { XKB_KEY_KP_Divide, XBMCK_KP_DIVIDE }, + { XKB_KEY_KP_Multiply, XBMCK_KP_MULTIPLY }, + { XKB_KEY_KP_Add, XBMCK_KP_PLUS }, + { XKB_KEY_KP_Separator, XBMCK_KP_MINUS }, + { XKB_KEY_KP_Equal, XBMCK_KP_EQUALS }, + { XKB_KEY_F1, XBMCK_F1 }, + { XKB_KEY_F2, XBMCK_F2 }, + { XKB_KEY_F3, XBMCK_F3 }, + { XKB_KEY_F4, XBMCK_F4 }, + { XKB_KEY_F5, XBMCK_F5 }, + { XKB_KEY_F6, XBMCK_F6 }, + { XKB_KEY_F7, XBMCK_F7 }, + { XKB_KEY_F8, XBMCK_F8 }, + { XKB_KEY_F9, XBMCK_F9 }, + { XKB_KEY_F10, XBMCK_F10 }, + { XKB_KEY_F11, XBMCK_F11 }, + { XKB_KEY_F12, XBMCK_F12 }, + { XKB_KEY_F13, XBMCK_F13 }, + { XKB_KEY_F14, XBMCK_F14 }, + { XKB_KEY_F15, XBMCK_F15 }, + { XKB_KEY_Caps_Lock, XBMCK_CAPSLOCK }, + { XKB_KEY_Shift_Lock, XBMCK_SCROLLOCK }, + { XKB_KEY_Shift_R, XBMCK_RSHIFT }, + { XKB_KEY_Shift_L, XBMCK_LSHIFT }, + { XKB_KEY_Alt_R, XBMCK_RALT }, + { XKB_KEY_Alt_L, XBMCK_LALT }, + { XKB_KEY_Control_R, XBMCK_RCTRL }, + { XKB_KEY_Control_L, XBMCK_LCTRL }, + { XKB_KEY_Meta_R, XBMCK_RMETA }, + { XKB_KEY_Meta_L, XBMCK_LMETA }, + { XKB_KEY_Super_R, XBMCK_RSUPER }, + { XKB_KEY_Super_L, XBMCK_LSUPER }, + { XKB_KEY_XF86Eject, XBMCK_EJECT }, + { XKB_KEY_XF86AudioStop, XBMCK_STOP }, + { XKB_KEY_XF86AudioRecord, XBMCK_RECORD }, + { XKB_KEY_XF86AudioRewind, XBMCK_REWIND }, + { XKB_KEY_XF86AudioPlay, XBMCK_PLAY }, + { XKB_KEY_XF86AudioRandomPlay, XBMCK_SHUFFLE }, + { XKB_KEY_XF86AudioForward, XBMCK_FASTFORWARD } + }; + + static const size_t navigationKeySymsSize = sizeof(navigationKeySyms) / + sizeof(navigationKeySyms[0]); + + for (size_t i = 0; i < navigationKeySymsSize; ++i) + { + if (navigationKeySyms[i].xkb == sym) + { + sym = navigationKeySyms[i].xbmc; + break; + } + } + } + + return sym; +} diff --git a/xbmc/input/linux/XKBCommonKeymap.h b/xbmc/input/linux/XKBCommonKeymap.h new file mode 100644 index 0000000000000..fbd6e33518519 --- /dev/null +++ b/xbmc/input/linux/XKBCommonKeymap.h @@ -0,0 +1,78 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "input/linux/Keymap.h" + +struct xkb_keymap; +struct xkb_state; + +typedef uint32_t xkb_mod_index_t; +typedef uint32_t xkb_mask_index_t; + +class IDllXKBCommon; + +class CXKBKeymap : public ILinuxKeymap +{ +public: + + CXKBKeymap(IDllXKBCommon &m_xkbCommonLibrary, + struct xkb_keymap *keymap); + ~CXKBKeymap(); + + static struct xkb_context * CreateXKBContext(IDllXKBCommon &xkbCommonLibrary); + /* ReceiveXKBKeymapFromSharedMemory does not own the file descriptor, as such it takes a const reference to it */ + static struct xkb_keymap * ReceiveXKBKeymapFromSharedMemory(IDllXKBCommon &xkbCommonLibrary, struct xkb_context *, const int &fd, uint32_t size); + static struct xkb_state * CreateXKBStateFromKeymap(IDllXKBCommon &xkbCommonLibrary, struct xkb_keymap *keymap); + static struct xkb_keymap * CreateXKBKeymapFromNames(IDllXKBCommon &xkbCommonLibrary, struct xkb_context *context, const std::string &rules, const std::string &model, const std::string &layout, const std::string &variant, const std::string &options); +private: + + uint32_t KeysymForKeycode(uint32_t code) const; + void UpdateMask(uint32_t depressed, + uint32_t latched, + uint32_t locked, + uint32_t group); + uint32_t CurrentModifiers() const; + uint32_t XBMCKeysymForKeycode(uint32_t code) const; + uint32_t ActiveXBMCModifiers() const; + + IDllXKBCommon &m_xkbCommonLibrary; + + struct xkb_keymap *m_keymap; + struct xkb_state *m_state; + + xkb_mod_index_t m_internalLeftControlIndex; + xkb_mod_index_t m_internalLeftShiftIndex; + xkb_mod_index_t m_internalLeftSuperIndex; + xkb_mod_index_t m_internalLeftAltIndex; + xkb_mod_index_t m_internalLeftMetaIndex; + + xkb_mod_index_t m_internalRightControlIndex; + xkb_mod_index_t m_internalRightShiftIndex; + xkb_mod_index_t m_internalRightSuperIndex; + xkb_mod_index_t m_internalRightAltIndex; + xkb_mod_index_t m_internalRightMetaIndex; + + xkb_mod_index_t m_internalCapsLockIndex; + xkb_mod_index_t m_internalNumLockIndex; + xkb_mod_index_t m_internalModeIndex; +}; diff --git a/xbmc/windowing/DllWaylandClient.h b/xbmc/windowing/DllWaylandClient.h new file mode 100644 index 0000000000000..edb6189edb2a4 --- /dev/null +++ b/xbmc/windowing/DllWaylandClient.h @@ -0,0 +1,193 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) + #include "config.h" +#endif + +#include + +#include "utils/log.h" +#include "DynamicDll.h" + +struct wl_proxy; +struct wl_interface; + +struct wl_display; +struct wl_registry; +struct wl_callback; +struct wl_compositor; +struct wl_shell; +struct wl_shell_surface; +struct wl_surface; +struct wl_seat; +struct wl_pointer; +struct wl_keyboard; +struct wl_output; +struct wl_region; + +extern const struct wl_interface wl_display_interface; +extern const struct wl_interface wl_registry_interface; +extern const struct wl_interface wl_callback_interface; +extern const struct wl_interface wl_compositor_interface; +extern const struct wl_interface wl_shell_interface; +extern const struct wl_interface wl_shell_surface_interface; +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface wl_seat_interface; +extern const struct wl_interface wl_pointer_interface; +extern const struct wl_interface wl_keyboard_interface; +extern const struct wl_interface wl_output_interface; +extern const struct wl_interface wl_region_interface; + +class IDllWaylandClient +{ +public: + typedef void(*wl_proxy_marshal_func)(struct wl_proxy *, + uint32_t, + ...); + typedef void(*wl_proxy_listener_func)(void); + typedef int(*wl_display_read_events_func)(struct wl_display *); + typedef int(*wl_display_prepare_read_func)(struct wl_display *); + + virtual struct wl_interface ** Get_wl_display_interface() = 0; + virtual struct wl_interface ** Get_wl_registry_interface() = 0; + virtual struct wl_interface ** Get_wl_callback_interface() = 0; + virtual struct wl_interface ** Get_wl_compositor_interface() = 0; + virtual struct wl_interface ** Get_wl_shell_interface() = 0; + virtual struct wl_interface ** Get_wl_shell_surface_interface() = 0; + virtual struct wl_interface ** Get_wl_surface_interface() = 0; + virtual struct wl_interface ** Get_wl_seat_interface() = 0; + virtual struct wl_interface ** Get_wl_pointer_interface() = 0; + virtual struct wl_interface ** Get_wl_keyboard_interface() = 0; + virtual struct wl_interface ** Get_wl_output_interface() = 0; + virtual struct wl_interface ** Get_wl_region_interface() = 0; + + virtual struct wl_display * wl_display_connect(const char *) = 0; + virtual void wl_display_disconnect(struct wl_display *) = 0; + virtual int wl_display_get_fd(struct wl_display *) = 0; + virtual wl_display_prepare_read_func wl_display_prepare_read_proc() = 0; + virtual wl_display_read_events_func wl_display_read_events_proc() = 0; + virtual int wl_display_dispatch_pending(struct wl_display *) = 0; + virtual int wl_display_dispatch(struct wl_display *) = 0; + virtual int wl_display_flush(struct wl_display *) = 0; + + virtual wl_proxy_marshal_func wl_proxy_marshaller() = 0; + + virtual struct wl_proxy * wl_proxy_create(struct wl_proxy *, + const struct wl_interface *) = 0; + virtual void wl_proxy_destroy(struct wl_proxy *) = 0; + virtual int wl_proxy_add_listener(struct wl_proxy *, + wl_proxy_listener_func *, + void *) = 0; + + virtual ~IDllWaylandClient() {} +}; + +class DllWaylandClient : public DllDynamic, public IDllWaylandClient +{ + DECLARE_DLL_WRAPPER(DllWaylandClient, DLL_PATH_WAYLAND_CLIENT) + + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_display_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_registry_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_callback_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_compositor_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_shell_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_shell_surface_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_surface_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_seat_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_pointer_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_keyboard_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_output_interface); + DEFINE_GLOBAL_PTR(struct wl_interface *, wl_region_interface); + + DEFINE_METHOD1(struct wl_display *, wl_display_connect, (const char *p1)); + DEFINE_METHOD1(void, wl_display_disconnect, (struct wl_display *p1)); + DEFINE_METHOD1(int, wl_display_get_fd, (struct wl_display *p1)); + DEFINE_METHOD_FP(int, wl_display_prepare_read, (struct wl_display *p1)); + DEFINE_METHOD_FP(int, wl_display_read_events, (struct wl_display *p1)); + DEFINE_METHOD1(int, wl_display_dispatch_pending, (struct wl_display *p1)); + DEFINE_METHOD1(int, wl_display_dispatch, (struct wl_display *p1)); + DEFINE_METHOD1(int, wl_display_flush, (struct wl_display *p1)); + + /* We need to resolve wl_proxy_marshal as a function pointer as it + * takes varargs */ + DEFINE_METHOD_FP(void, + wl_proxy_marshal, + (struct wl_proxy *p1, uint32_t p2, ...)); + + DEFINE_METHOD2(struct wl_proxy *, + wl_proxy_create, + (struct wl_proxy *p1, const struct wl_interface *p2)); + DEFINE_METHOD1(void, wl_proxy_destroy, (struct wl_proxy *p1)); + DEFINE_METHOD3(int, + wl_proxy_add_listener, + (struct wl_proxy *p1, + wl_proxy_listener_func *p2, + void *p3)); + + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD(wl_display_interface) + RESOLVE_METHOD(wl_registry_interface) + RESOLVE_METHOD(wl_callback_interface) + RESOLVE_METHOD(wl_compositor_interface) + RESOLVE_METHOD(wl_shell_interface) + RESOLVE_METHOD(wl_shell_surface_interface) + RESOLVE_METHOD(wl_surface_interface) + RESOLVE_METHOD(wl_seat_interface) + RESOLVE_METHOD(wl_pointer_interface) + RESOLVE_METHOD(wl_keyboard_interface) + RESOLVE_METHOD(wl_output_interface) + RESOLVE_METHOD(wl_region_interface) + + RESOLVE_METHOD(wl_display_connect) + RESOLVE_METHOD(wl_display_disconnect) + RESOLVE_METHOD(wl_display_get_fd) + RESOLVE_METHOD_OPTIONAL_FP(wl_display_prepare_read) + RESOLVE_METHOD_OPTIONAL_FP(wl_display_read_events) + RESOLVE_METHOD(wl_display_dispatch_pending) + RESOLVE_METHOD(wl_display_dispatch) + RESOLVE_METHOD(wl_display_flush) + RESOLVE_METHOD_FP(wl_proxy_marshal) + RESOLVE_METHOD(wl_proxy_create) + RESOLVE_METHOD(wl_proxy_destroy) + RESOLVE_METHOD(wl_proxy_add_listener) + END_METHOD_RESOLVE() + +public: + + /* This overload returns the function pointer to wl_proxy_marshal + * so that clients can call it directly */ + wl_proxy_marshal_func wl_proxy_marshaller() + { + return DllWaylandClient::wl_proxy_marshal; + } + + wl_display_prepare_read_func wl_display_prepare_read_proc() + { + return DllWaylandClient::wl_display_prepare_read; + } + + wl_display_read_events_func wl_display_read_events_proc() + { + return DllWaylandClient::wl_display_read_events; + } +}; diff --git a/xbmc/windowing/DllWaylandEgl.h b/xbmc/windowing/DllWaylandEgl.h new file mode 100644 index 0000000000000..c72d3f9d804cb --- /dev/null +++ b/xbmc/windowing/DllWaylandEgl.h @@ -0,0 +1,65 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) + #include "config.h" +#endif +#include "utils/log.h" +#include "DynamicDll.h" + +struct wl_surface; +struct wl_egl_window; + +class IDllWaylandEGL +{ +public: + virtual ~IDllWaylandEGL() {} + virtual struct wl_egl_window * wl_egl_window_create(struct wl_surface *, + int width, + int height) = 0; + virtual void wl_egl_window_destroy(struct wl_egl_window *) = 0; + virtual void wl_egl_window_resize(struct wl_egl_window *, + int width, int height, + int dx, int dy) = 0; +}; + +class DllWaylandEGL : public DllDynamic, public IDllWaylandEGL +{ + DECLARE_DLL_WRAPPER(DllWaylandEGL, DLL_PATH_WAYLAND_EGL) + + DEFINE_METHOD3(struct wl_egl_window *, + wl_egl_window_create, + (struct wl_surface *p1, int p2, int p3)); + DEFINE_METHOD1(void, wl_egl_window_destroy, (struct wl_egl_window *p1)); + DEFINE_METHOD5(void, + wl_egl_window_resize, + (struct wl_egl_window *p1, + int p2, + int p3, + int p4, + int p5)); + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD(wl_egl_window_create) + RESOLVE_METHOD(wl_egl_window_destroy) + RESOLVE_METHOD(wl_egl_window_resize) + END_METHOD_RESOLVE() +}; diff --git a/xbmc/windowing/DllXKBCommon.h b/xbmc/windowing/DllXKBCommon.h new file mode 100644 index 0000000000000..97a721b89ea1c --- /dev/null +++ b/xbmc/windowing/DllXKBCommon.h @@ -0,0 +1,92 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) + #include "config.h" +#endif +#include +#include "utils/log.h" +#include "DynamicDll.h" + +class IDllXKBCommon +{ +public: + virtual ~IDllXKBCommon() {} + + virtual struct xkb_context * xkb_context_new(enum xkb_context_flags) = 0; + virtual void xkb_context_unref(struct xkb_context *) = 0; + virtual struct xkb_keymap * xkb_keymap_new_from_string(struct xkb_context *, + const char *, + enum xkb_keymap_format, + enum xkb_keymap_compile_flags) = 0; + virtual struct xkb_keymap * xkb_keymap_new_from_names(struct xkb_context *, + const struct xkb_rule_names *, + enum xkb_keymap_compile_flags) = 0; + virtual xkb_mod_index_t xkb_keymap_mod_get_index(struct xkb_keymap *, + const char *) = 0; + virtual void xkb_keymap_unref(struct xkb_keymap *) = 0; + virtual struct xkb_state * xkb_state_new(struct xkb_keymap *) = 0; + virtual xkb_mod_mask_t xkb_state_serialize_mods(struct xkb_state *, + enum xkb_state_component) = 0; + virtual enum xkb_state_component xkb_state_update_mask (struct xkb_state *, + xkb_mod_mask_t, + xkb_mod_mask_t, + xkb_mod_mask_t, + xkb_layout_index_t, + xkb_layout_index_t, + xkb_layout_index_t) = 0; + virtual uint32_t xkb_state_key_get_syms(struct xkb_state *, + uint32_t, + const xkb_keysym_t **) = 0; + virtual void xkb_state_unref(struct xkb_state *) = 0; +}; + +class DllXKBCommon : public DllDynamic, public IDllXKBCommon +{ + DECLARE_DLL_WRAPPER(DllXKBCommon, DLL_PATH_XKBCOMMON) + + DEFINE_METHOD1(struct xkb_context *, xkb_context_new, (enum xkb_context_flags p1)); + DEFINE_METHOD1(void, xkb_context_unref, (struct xkb_context *p1)); + DEFINE_METHOD4(struct xkb_keymap *, xkb_keymap_new_from_string, (struct xkb_context *p1, const char *p2, enum xkb_keymap_format p3, enum xkb_keymap_compile_flags p4)); + DEFINE_METHOD3(struct xkb_keymap *, xkb_keymap_new_from_names, (struct xkb_context *p1, const struct xkb_rule_names *p2, enum xkb_keymap_compile_flags p3)); + DEFINE_METHOD2(xkb_mod_index_t, xkb_keymap_mod_get_index, (struct xkb_keymap *p1, const char *p2)); + DEFINE_METHOD1(void, xkb_keymap_unref, (struct xkb_keymap *p1)); + DEFINE_METHOD1(struct xkb_state *, xkb_state_new, (struct xkb_keymap *p1)); + DEFINE_METHOD2(xkb_mod_mask_t, xkb_state_serialize_mods, (struct xkb_state *p1, enum xkb_state_component p2)); + DEFINE_METHOD7(enum xkb_state_component, xkb_state_update_mask, (struct xkb_state *p1, xkb_mod_mask_t p2, xkb_mod_mask_t p3, xkb_mod_mask_t p4, xkb_layout_index_t p5, xkb_layout_index_t p6, xkb_layout_index_t p7)); + DEFINE_METHOD3(uint32_t, xkb_state_key_get_syms, (struct xkb_state *p1, uint32_t p2, const xkb_keysym_t **p3)); + DEFINE_METHOD1(void, xkb_state_unref, (struct xkb_state *p1)); + + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD(xkb_context_new) + RESOLVE_METHOD(xkb_context_unref) + RESOLVE_METHOD(xkb_keymap_new_from_string) + RESOLVE_METHOD(xkb_keymap_new_from_names) + RESOLVE_METHOD(xkb_keymap_mod_get_index) + RESOLVE_METHOD(xkb_keymap_unref) + RESOLVE_METHOD(xkb_state_new) + RESOLVE_METHOD(xkb_state_serialize_mods) + RESOLVE_METHOD(xkb_state_update_mask) + RESOLVE_METHOD(xkb_state_key_get_syms) + RESOLVE_METHOD(xkb_state_unref) + END_METHOD_RESOLVE() +}; diff --git a/xbmc/windowing/WaylandProtocol.h b/xbmc/windowing/WaylandProtocol.h new file mode 100644 index 0000000000000..945b63f99a8e5 --- /dev/null +++ b/xbmc/windowing/WaylandProtocol.h @@ -0,0 +1,244 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include +#include +#include + +#include "DllWaylandClient.h" + +/* These functions are wrappers around using the wayland protocol + * directly. Unfortunately, since most of the protocol has autogenerated + * binding code, and that binding code assumes that we're directly + * linked to the client library (we're not), we can't use it. So + * we need to use wl_proxy_create, wl_proxy_marshal and wl_proxy_destory + * directly. + * + * These functions effectively exist to reduce some of the duplication + * that surrounds using these functions directly. You should look + * at the autogenerated binding code to determine how wl_proxy_marshal + * should be used to call a particular method. + * + * Also note that there may be some cases where additional constructor + * or destructor functions might need to be called before or after + * CreateWaylandObject and DestroyWaylandObject. + * + * If you need to call a method with more than six arguments, + * you'll need to add a new overload here */ +namespace xbmc +{ +namespace wayland +{ +namespace protocol +{ +/* These functions call a method on a specifed wayland object + * (you should use the pointer provided by the client library + * and not the wrapper) with the specified opcode and + * arguments. + * + * THERE IS NO TYPE CHECKING so you should be especially sure that + * you're calling it with the right arguments. Failure to do so + * will result in very strange behaviour + */ +template +void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, + Object object, + uint32_t opcode) +{ + struct wl_proxy *proxy = + reinterpret_cast(object); + clientLibrary.wl_proxy_marshaller()(proxy, + opcode); +} +template +void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, + Object object, + uint32_t opcode, + A1 arg1) +{ + struct wl_proxy *proxy = + reinterpret_cast(object); + clientLibrary.wl_proxy_marshaller()(proxy, + opcode, + arg1); +} + +template +void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, + Object object, + uint32_t opcode, + A1 arg1, + A2 arg2) +{ + struct wl_proxy *proxy = + reinterpret_cast(object); + clientLibrary.wl_proxy_marshaller()(proxy, + opcode, + arg1, + arg2); +} + +template +void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, + Object object, + uint32_t opcode, + A1 arg1, + A2 arg2, + A3 arg3) +{ + struct wl_proxy *proxy = + reinterpret_cast(object); + clientLibrary.wl_proxy_marshaller()(proxy, + opcode, + arg1, + arg2, + arg3); +} + +template +void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, + Object object, + uint32_t opcode, + A1 arg1, + A2 arg2, + A3 arg3, + A4 arg4) +{ + struct wl_proxy *proxy = + reinterpret_cast(object); + clientLibrary.wl_proxy_marshaller()(proxy, + opcode, + arg1, + arg2, + arg3, + arg4); +} + +template +void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, + Object object, + uint32_t opcode, + A1 arg1, + A2 arg2, + A3 arg3, + A4 arg4, + A5 arg5) +{ + struct wl_proxy *proxy = + reinterpret_cast(object); + clientLibrary.wl_proxy_marshaller()(proxy, + opcode, + arg1, + arg2, + arg3, + arg4, + arg5); +} + +/* This function template returns a new unmanaged object pointer + * as specified by Create with the RPC interface as specified + * as a child in the server ownership hierarchy of factory. + * + * Create must be castable to struct wl_proxy *, which + * means that struct wl_proxy should be its first member. Generally + * all wayland library proxy objects satisfy this criteria + */ +template +Create CreateWaylandObject(IDllWaylandClient &clientLibrary, + Factory factory, + struct wl_interface **interface) +{ + struct wl_proxy *pfactory = + reinterpret_cast(factory); + struct wl_proxy *proxy = + clientLibrary.wl_proxy_create(pfactory, + reinterpret_cast(interface)); + + if (!proxy) + { + std::stringstream ss; + ss << "Failed to create " + << typeid(Create).name() + << " from factory " + << typeid(Factory).name() + << " at 0x" + << std::hex + << reinterpret_cast(pfactory) + << std::dec; + throw std::runtime_error(ss.str()); + } + + return reinterpret_cast(proxy); +} + +/* This function adds a new "listener" to the object specified. + * A "listener" is generally a struct of function pointers as specified + * by the object's RPC interface for each event it can generate. These + * can usually be found in the protocol header. "data" is passed + * to each callback to make it a full closure. */ +template +int AddListenerOnWaylandObject(IDllWaylandClient &clientLibrary, + Object object, + Listener listener, + void *data) +{ + struct wl_proxy *proxy = + reinterpret_cast(object); + + /* C-style casts are bad, but there is no equavilent to + * std::remove_const in C++98 and we are reinterpret_cast'ing + * anyways */ + IDllWaylandClient::wl_proxy_listener_func *listenerFunc = + (IDllWaylandClient::wl_proxy_listener_func *)((void *)listener); + return clientLibrary.wl_proxy_add_listener(proxy, listenerFunc, data); +} + +/* This function destroys the proxy object and releases its resources + * on the client side. There may be an additional destroy request to + * release resources on the server side. That must be called + * prior to this. */ +template +void DestroyWaylandObject(IDllWaylandClient &clientLibrary, + Object *object) +{ + struct wl_proxy *proxy = + reinterpret_cast(object); + clientLibrary.wl_proxy_destroy(proxy); +} +} +} +} diff --git a/xbmc/windowing/WinEvents.cpp b/xbmc/windowing/WinEvents.cpp index 36c5fabe0dcfe..22fe2bcc401de 100644 --- a/xbmc/windowing/WinEvents.cpp +++ b/xbmc/windowing/WinEvents.cpp @@ -46,6 +46,10 @@ #include "WinEventsX11.h" #define WinEventsType CWinEventsX11 +#elif defined(HAVE_WAYLAND) +#include "WinEventsWayland.h" +#define WinEventsType CWinEventsWayland + #elif defined(TARGET_LINUX) && defined(HAS_LINUX_EVENTS) #include "WinEventsLinux.h" #define WinEventsType CWinEventsLinux diff --git a/xbmc/windowing/WinEventsWayland.cpp b/xbmc/windowing/WinEventsWayland.cpp new file mode 100644 index 0000000000000..d46870cbde919 --- /dev/null +++ b/xbmc/windowing/WinEventsWayland.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "system.h" + +#if defined (HAVE_WAYLAND) + +#include + +#include "Application.h" +#include "xbmc/windowing/WindowingFactory.h" +#include "WinEventsWayland.h" + +#include "wayland/EventListener.h" +#include "wayland/InputFactory.h" +#include "wayland/EventLoop.h" + +namespace xwe = xbmc::wayland::events; + +namespace +{ +class XBMCListener : + public xbmc::IEventListener +{ +public: + + virtual void OnEvent(XBMC_Event &event); + virtual void OnFocused(); + virtual void OnUnfocused(); +}; + +XBMCListener g_listener; +boost::scoped_ptr g_inputInstance; +boost::scoped_ptr g_eventLoop; +} + +void XBMCListener::OnEvent(XBMC_Event &e) +{ + g_application.OnEvent(e); +} + +void XBMCListener::OnFocused() +{ + g_application.m_AppFocused = true; + g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); +} + +void XBMCListener::OnUnfocused() +{ + g_application.m_AppFocused = false; + g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); +} + +CWinEventsWayland::CWinEventsWayland() +{ +} + +void CWinEventsWayland::RefreshDevices() +{ +} + +bool CWinEventsWayland::IsRemoteLowBattery() +{ + return false; +} + +/* This function reads the display connection and dispatches + * any events through the specified object listeners */ +bool CWinEventsWayland::MessagePump() +{ + if (!g_eventLoop.get()) + return false; + + g_eventLoop->Dispatch(); + + return true; +} + +size_t CWinEventsWayland::GetQueueSize() +{ + /* We can't query the size of the queue */ + return 0; +} + +void CWinEventsWayland::SetEventQueueStrategy(xwe::IEventQueueStrategy &strategy) +{ + g_eventLoop.reset(new xwe::Loop(g_listener, strategy)); +} + +void CWinEventsWayland::DestroyEventQueueStrategy() +{ + g_eventLoop.reset(); +} + +/* Once we know about a wayland seat, we can just create our manager + * object to encapsulate all of that state. When the seat goes away + * we just unset the manager object and it is all cleaned up at that + * point */ +void CWinEventsWayland::SetWaylandSeat(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + struct wl_seat *s) +{ + if (!g_eventLoop.get()) + throw std::logic_error("Must have a wl_display set before setting " + "the wl_seat in CWinEventsWayland "); + + g_inputInstance.reset(new xbmc::InputFactory(clientLibrary, + xkbCommonLibrary, + s, + *g_eventLoop, + *g_eventLoop)); +} + +void CWinEventsWayland::DestroyWaylandSeat() +{ + g_inputInstance.reset(); +} + +/* When a surface becomes available, this function should be called + * to register it as the current one for processing input events on. + * + * It is a precondition violation to call this function before + * a seat has been registered */ +void CWinEventsWayland::SetXBMCSurface(struct wl_surface *s) +{ + if (!g_inputInstance.get()) + throw std::logic_error("Must have a wl_seat set before setting " + "the wl_surface in CWinEventsWayland"); + + g_inputInstance->SetXBMCSurface(s); +} + +#endif diff --git a/xbmc/windowing/WinEventsWayland.h b/xbmc/windowing/WinEventsWayland.h new file mode 100644 index 0000000000000..932cfd272bcf1 --- /dev/null +++ b/xbmc/windowing/WinEventsWayland.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#ifndef WINDOW_EVENTS_WAYLAND_H +#define WINDOW_EVENTS_WAYLAND_H + +#pragma once +#include "windowing/WinEvents.h" + +struct wl_display; +struct wl_seat; +struct wl_surface; + +class IDllWaylandClient; +class IDllXKBCommon; + +namespace xbmc +{ +namespace wayland +{ +namespace events +{ +class IEventQueueStrategy; +} +} +} + +class CWinEventsWayland : public IWinEvents +{ +public: + CWinEventsWayland(); + bool MessagePump(); + size_t GetQueueSize(); + static void RefreshDevices(); + static bool IsRemoteLowBattery(); + + static void SetEventQueueStrategy(xbmc::wayland::events::IEventQueueStrategy &strategy); + static void DestroyEventQueueStrategy(); + + static void SetWaylandSeat(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + struct wl_seat *seat); + static void DestroyWaylandSeat(); + + static void SetXBMCSurface(struct wl_surface *surf); +}; + +#endif diff --git a/xbmc/windowing/egl/EGLNativeTypeWayland.cpp b/xbmc/windowing/egl/EGLNativeTypeWayland.cpp new file mode 100644 index 0000000000000..ef45bb1567408 --- /dev/null +++ b/xbmc/windowing/egl/EGLNativeTypeWayland.cpp @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "system.h" + +#if defined(HAVE_WAYLAND) + +#define WL_EGL_PLATFORM + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/DllWaylandEgl.h" +#include "windowing/DllXKBCommon.h" +#include "windowing/WaylandProtocol.h" + +#include "guilib/gui3d.h" +#include "utils/log.h" +#include "windowing/WinEvents.h" +#include "windowing/WinEventsWayland.h" + +#include "wayland/WaylandLibraries.h" +#include "wayland/XBMCConnection.h" +#include "wayland/XBMCSurface.h" + +#endif + +#include "EGLNativeTypeWayland.h" + +#if defined(HAVE_WAYLAND) +namespace xw = xbmc::wayland; + +class CEGLNativeTypeWayland::Private +{ +public: + + boost::scoped_ptr m_libraries; + boost::scoped_ptr m_connection; + boost::scoped_ptr m_surface; + + bool LoadWaylandLibraries(); + void UnloadWaylandLibraries(); +}; + +bool CEGLNativeTypeWayland::Private::LoadWaylandLibraries() +{ + try + { + m_libraries.reset(new xw::Libraries()); + } + catch (const std::runtime_error &err) + { + CLog::Log(LOGWARNING, "%s: %s\n", + __FUNCTION__, err.what()); + return false; + } + + return true; +} + +void CEGLNativeTypeWayland::Private::UnloadWaylandLibraries() +{ + m_libraries.reset(); +} + +#else +class CEGLNativeTypeWayland::Private +{ +}; +#endif + +CEGLNativeTypeWayland::CEGLNativeTypeWayland() : + priv(new Private()) +{ +} + +CEGLNativeTypeWayland::~CEGLNativeTypeWayland() +{ +} + +bool CEGLNativeTypeWayland::CheckCompatibility() +{ +#if defined(HAVE_WAYLAND) + /* FIXME: + * There appears to be a bug in DllDynamic::CanLoad() which causes + * it to always return false. We are just loading the library + * directly at CheckCompatibility time now */ + if (!priv->LoadWaylandLibraries()) + return false; + + return true; +#else + return false; +#endif +} + +void CEGLNativeTypeWayland::Initialize() +{ +} + +void CEGLNativeTypeWayland::Destroy() +{ +#if defined(HAVE_WAYLAND) + priv->UnloadWaylandLibraries(); +#endif +} + +int CEGLNativeTypeWayland::GetQuirks() +{ + return EGL_QUIRK_DONT_TRUST_SURFACE_SIZE; +} + +bool CEGLNativeTypeWayland::CreateNativeDisplay() +{ +#if defined(HAVE_WAYLAND) + + /* On CreateNativeDisplay we connect to the running wayland + * compositor on our current socket (as specified by WAYLAND_DISPLAY) + * and then do some initial set up like registering event handlers. + * + * xbmc::wayland::XBMCConnection is an encapsulation of all of our + * current global state with regards to a wayland connection. We + * need to give it access to the wayland client libraries and + * libxkbcommon for it to do its work. + * + * We also inject an xbmc::wayland::XBMCConnection::EventInjector + * which is basically just a table of function pointers to functions + * in CWinEventsWayland, which are all static. CWinEvents is still + * effectively a static, singleton class, and depending on it + * means that testing becomes substantially more difficult. As such + * we just inject the bits that we need here so that they can be + * stubbed out later in testing environments if need be. + * + * xbmc::wayland::XBMCConnection's constructor will throw an + * std::runtime_error in case it runs into any trouble in connecting + * to the wayland compositor or getting the initial global objects. + * + * The best we can do when that happens is just report the error + * and bail out, possibly to try another (fallback) windowing system. + */ + try + { + xw::XBMCConnection::EventInjector injector = + { + CWinEventsWayland::SetEventQueueStrategy, + CWinEventsWayland::DestroyEventQueueStrategy, + CWinEventsWayland::SetWaylandSeat, + CWinEventsWayland::DestroyWaylandSeat, + CWinEvents::MessagePump + }; + + priv->m_connection.reset(new xw::XBMCConnection(priv->m_libraries->ClientLibrary(), + priv->m_libraries->XKBCommonLibrary(), + injector)); + } + catch (const std::runtime_error &err) + { + CLog::Log(LOGERROR, "%s: %s", __FUNCTION__, err.what()); + return false; + } + + return true; +#else + return false; +#endif +} + +bool CEGLNativeTypeWayland::CreateNativeWindow() +{ +#if defined(HAVE_WAYLAND) + + /* CreateNativeWindow is where we allocate a new wayland surface + * using libwayland-egl and ask the compositor to display it by + * creating a new remote surface object. + * + * xbmc::wayland::XBMCSurface encapsulates all of this information. It + * needs access to various client libraries, as well as the compositor + * and shell global interfaces from xbmc::wayland::XBMCConnection + * in order to actually create the internal "surface" and "shell + * surface" representations. + * + * Once xbmc::wayland::XBMCSurface is created, an EGL bindable + * surface will be available for later use. + * + * The last two parameters are the requested width and height of + * the surface. + * + * If any problems are encountered in creating the surface + * an std::runtime_error is thrown. Like above, we catch it and + * report the error, since there's not much we can do about it. + */ + try + { + RESOLUTION_INFO info; + priv->m_connection->CurrentResolution(info); + + xw::XBMCSurface::EventInjector injector = + { + CWinEventsWayland::SetXBMCSurface + }; + + priv->m_surface.reset(new xw::XBMCSurface(priv->m_libraries->ClientLibrary(), + priv->m_libraries->EGLLibrary(), + injector, + priv->m_connection->GetCompositor(), + priv->m_connection->GetShell(), + info.iScreenWidth, + info.iScreenHeight)); + } + catch (const std::runtime_error &err) + { + CLog::Log(LOGERROR, "%s: %s", __FUNCTION__, err.what()); + return false; + } + + return true; +#else + return false; +#endif +} + +bool CEGLNativeTypeWayland::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const +{ +#if defined(HAVE_WAYLAND) + /* We need to return a pointer to the wl_display * (eg wl_display **), + * as EGLWrapper needs to dereference our return value to get the + * actual display and not its first member */ + *nativeDisplay = + reinterpret_cast (priv->m_connection->NativeDisplay()); + return true; +#else + return false; +#endif +} + +bool CEGLNativeTypeWayland::GetNativeWindow(XBNativeDisplayType **nativeWindow) const +{ +#if defined(HAVE_WAYLAND) + *nativeWindow = + reinterpret_cast (priv->m_surface->EGLNativeWindow()); + return true; +#else + return false; +#endif +} + +/* DestroyNativeDisplay and DestroyNativeWindow simply just call + * reset on the relevant scoped_ptr. This will effectively destroy + * the encapsulating objects which cleans up all of the relevant + * connections and surfaces */ +bool CEGLNativeTypeWayland::DestroyNativeDisplay() +{ +#if defined(HAVE_WAYLAND) + priv->m_connection.reset(); + return true; +#else + return false; +#endif +} + +bool CEGLNativeTypeWayland::DestroyNativeWindow() +{ +#if defined(HAVE_WAYLAND) + priv->m_surface.reset(); + return true; +#else + return false; +#endif +} + +/* The connection knowns about the resolution size, so we ask it + * about it. This information is all cached locally, but stored in + * the xbmc::wayland::XBMCConnection object */ +bool CEGLNativeTypeWayland::GetNativeResolution(RESOLUTION_INFO *res) const +{ +#if defined(HAVE_WAYLAND) + priv->m_connection->CurrentResolution(*res); + return true; +#else + return false; +#endif +} + +bool CEGLNativeTypeWayland::SetNativeResolution(const RESOLUTION_INFO &res) +{ +#if defined(HAVE_WAYLAND) + priv->m_surface->Resize(res.iScreenWidth, res.iScreenHeight); + return true; +#else + return false; +#endif +} + +bool CEGLNativeTypeWayland::ProbeResolutions(std::vector &resolutions) +{ +#if defined(HAVE_WAYLAND) + priv->m_connection->AvailableResolutions(resolutions); + return true; +#else + return false; +#endif +} + +bool CEGLNativeTypeWayland::GetPreferredResolution(RESOLUTION_INFO *res) const +{ +#if defined(HAVE_WAYLAND) + priv->m_connection->PreferredResolution(*res); + return true; +#else + return false; +#endif +} + +bool CEGLNativeTypeWayland::ShowWindow(bool show) +{ +#if defined(HAVE_WAYLAND) + + /* XBMC lacks a way to select the output it should appear on, + * so we always appear on the first output */ + if (show) + priv->m_surface->Show(priv->m_connection->GetFirstOutput()); + else + return false; + + return true; +#else + return false; +#endif +} diff --git a/xbmc/windowing/egl/EGLNativeTypeWayland.h b/xbmc/windowing/egl/EGLNativeTypeWayland.h new file mode 100644 index 0000000000000..301c16c53b615 --- /dev/null +++ b/xbmc/windowing/egl/EGLNativeTypeWayland.h @@ -0,0 +1,58 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include + +#include +#include "EGLNativeType.h" + +class CEGLNativeTypeWayland : public CEGLNativeType +{ +public: + CEGLNativeTypeWayland(); + virtual ~CEGLNativeTypeWayland(); + virtual std::string GetNativeName() const { return "wayland"; }; + virtual bool CheckCompatibility(); + virtual void Initialize(); + virtual void Destroy(); + virtual int GetQuirks(); + + virtual bool CreateNativeDisplay(); + virtual bool CreateNativeWindow(); + virtual bool GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const; + virtual bool GetNativeWindow(XBNativeWindowType **nativeWindow) const; + + virtual bool DestroyNativeWindow(); + virtual bool DestroyNativeDisplay(); + + virtual bool GetNativeResolution(RESOLUTION_INFO *res) const; + virtual bool SetNativeResolution(const RESOLUTION_INFO &res); + virtual bool ProbeResolutions(std::vector &resolutions); + virtual bool GetPreferredResolution(RESOLUTION_INFO *res) const; + + virtual bool ShowWindow(bool show); +private: + + class Private; + + boost::scoped_ptr priv; +}; diff --git a/xbmc/windowing/egl/EGLQuirks.h b/xbmc/windowing/egl/EGLQuirks.h index 6624f23e01f10..28e25f7c0caba 100644 --- a/xbmc/windowing/egl/EGLQuirks.h +++ b/xbmc/windowing/egl/EGLQuirks.h @@ -35,6 +35,11 @@ */ #define EGL_QUIRK_DESTROY_NATIVE_WINDOW_WITH_SURFACE (1 << 1) +/*! \brief The intel driver on wayland is broken and always returns a surface + size of -1, -1. Work around it for now +*/ +#define EGL_QUIRK_DONT_TRUST_SURFACE_SIZE (1 << 2) + /*! \brief Some drivers destroy the native display on resolution change. xbmc's EGL implementation is not aware of this change. In that case a Reinit of the display needs to be done. diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp index 5006b94186017..c058f2cc55fd6 100644 --- a/xbmc/windowing/egl/EGLWrapper.cpp +++ b/xbmc/windowing/egl/EGLWrapper.cpp @@ -22,6 +22,9 @@ #ifdef HAS_EGL #include "utils/log.h" #include +#if defined(HAVE_WAYLAND) + #include "EGLNativeTypeWayland.h" +#endif #if defined(TARGET_ANDROID) #include "EGLNativeTypeAndroid.h" #if defined(HAS_LIBAMCODEC) @@ -99,6 +102,8 @@ bool CEGLWrapper::Initialize(const std::string &implementation) (nativeGuess = CreateEGLNativeType(implementation)) #elif defined(TARGET_ANDROID) (nativeGuess = CreateEGLNativeType(implementation)) +#elif defined(HAVE_WAYLAND) + (nativeGuess = CreateEGLNativeType(implementation)) #elif defined(TARGET_RASPBERRY_PI) (nativeGuess = CreateEGLNativeType(implementation)) #elif defined(HAS_IMXVPU) @@ -301,6 +306,11 @@ bool CEGLWrapper::CreateSurface(EGLDisplay display, EGLConfig config, EGLSurface return *surface != EGL_NO_SURFACE; } +bool CEGLWrapper::TrustSurfaceSize() +{ + return !(m_nativeTypes->GetQuirks() & EGL_QUIRK_DONT_TRUST_SURFACE_SIZE); +} + bool CEGLWrapper::GetSurfaceSize(EGLDisplay display, EGLSurface surface, EGLint *width, EGLint *height) { if (!width || !height) diff --git a/xbmc/windowing/egl/EGLWrapper.h b/xbmc/windowing/egl/EGLWrapper.h index 5a748685de4d0..9fec9d4d3c684 100644 --- a/xbmc/windowing/egl/EGLWrapper.h +++ b/xbmc/windowing/egl/EGLWrapper.h @@ -67,6 +67,8 @@ class CEGLWrapper bool GetConfigAttrib(EGLDisplay display, EGLConfig config, EGLint attribute, EGLint *value); bool SurfaceAttrib(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint value); + bool TrustSurfaceSize(); + static void* GetProcAddress(const char* function); private: diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp index 852f3370e0e61..60a1a8dce7a39 100644 --- a/xbmc/windowing/egl/WinSystemEGL.cpp +++ b/xbmc/windowing/egl/WinSystemEGL.cpp @@ -186,13 +186,20 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res) } } - int width = 0, height = 0; - if (!m_egl->GetSurfaceSize(m_display, m_surface, &width, &height)) + /* The intel driver on wayland is broken and always returns a surface + * size of -1, -1. Work around it for now */ + if (m_egl->TrustSurfaceSize()) { - CLog::Log(LOGERROR, "%s: Surface is invalid",__FUNCTION__); - return false; + int width = 0, height = 0; + if (!m_egl->GetSurfaceSize(m_display, m_surface, &width, &height)) + { + CLog::Log(LOGERROR, "%s: Surface is invalid",__FUNCTION__); + return false; + } + CLog::Log(LOGDEBUG, "%s: Created surface of size %ix%i",__FUNCTION__, width, height); } - CLog::Log(LOGDEBUG, "%s: Created surface of size %ix%i",__FUNCTION__, width, height); + else + CLog::Log(LOGDEBUG, "%s: Cannot reliably get surface size with this backend",__FUNCTION__); EGLint contextAttrs[] = { diff --git a/xbmc/windowing/egl/wayland/Callback.cpp b/xbmc/windowing/egl/wayland/Callback.cpp new file mode 100644 index 0000000000000..45d0befa72c02 --- /dev/null +++ b/xbmc/windowing/egl/wayland/Callback.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Callback.h" + +namespace xw = xbmc::wayland; + +const wl_callback_listener xw::Callback::m_listener = +{ + Callback::OnCallback +}; + +xw::Callback::Callback(IDllWaylandClient &clientLibrary, + struct wl_callback *callback, + const Func &func) : + m_clientLibrary(clientLibrary), + m_callback(callback), + m_func(func) +{ + protocol::AddListenerOnWaylandObject(m_clientLibrary, + m_callback, + &m_listener, + reinterpret_cast(this)); +} + +xw::Callback::~Callback() +{ + protocol::DestroyWaylandObject(m_clientLibrary, + m_callback); +} + +struct wl_callback * +xw::Callback::GetWlCallback() +{ + return m_callback; +} + +void +xw::Callback::OnCallback(void *data, + struct wl_callback *callback, + uint32_t time) +{ + static_cast(data)->m_func(time); +} diff --git a/xbmc/windowing/egl/wayland/Callback.h b/xbmc/windowing/egl/wayland/Callback.h new file mode 100644 index 0000000000000..6ae6df21845dc --- /dev/null +++ b/xbmc/windowing/egl/wayland/Callback.h @@ -0,0 +1,65 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include + +class IDllWaylandClient; + +namespace xbmc +{ +namespace wayland +{ +/* Callback encapsulates a callback object that might be called + * by the compositor through the client library at an arbitrary point + * in time. A custom closure can be provided as func to be called + * whenever this callback is fired + */ +class Callback : + boost::noncopyable +{ +public: + + typedef boost::function Func; + + Callback(IDllWaylandClient &clientLibrary, + struct wl_callback *callback, + const Func &func); + ~Callback(); + + struct wl_callback * GetWlCallback(); + + static const struct wl_callback_listener m_listener; + + static void OnCallback(void *, + struct wl_callback *, + uint32_t); + +private: + + IDllWaylandClient &m_clientLibrary; + struct wl_callback *m_callback; + Func m_func; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/Compositor.cpp b/xbmc/windowing/egl/wayland/Compositor.cpp new file mode 100644 index 0000000000000..df0f52e5b9ae6 --- /dev/null +++ b/xbmc/windowing/egl/wayland/Compositor.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Compositor.h" + +namespace xw = xbmc::wayland; + +xw::Compositor::Compositor(IDllWaylandClient &clientLibrary, + struct wl_compositor *compositor) : + m_clientLibrary(clientLibrary), + m_compositor(compositor) +{ +} + +xw::Compositor::~Compositor() +{ + protocol::DestroyWaylandObject(m_clientLibrary, + m_compositor); +} + +struct wl_compositor * +xw::Compositor::GetWlCompositor() +{ + return m_compositor; +} + +struct wl_surface * +xw::Compositor::CreateSurface() const +{ + struct wl_surface *surface = + protocol::CreateWaylandObject(m_clientLibrary, + m_compositor, + m_clientLibrary.Get_wl_surface_interface()); + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_compositor, + WL_COMPOSITOR_CREATE_SURFACE, + surface); + return surface; +} + +struct wl_region * +xw::Compositor::CreateRegion() const +{ + struct wl_region *region = + protocol::CreateWaylandObject(m_clientLibrary, + m_compositor, + m_clientLibrary.Get_wl_region_interface ()); + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_compositor, + WL_COMPOSITOR_CREATE_REGION, + region); + return region; +} diff --git a/xbmc/windowing/egl/wayland/Compositor.h b/xbmc/windowing/egl/wayland/Compositor.h new file mode 100644 index 0000000000000..93d2e8d1ed021 --- /dev/null +++ b/xbmc/windowing/egl/wayland/Compositor.h @@ -0,0 +1,61 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +struct wl_compositor; +struct wl_surface; +struct wl_region; + +class IDllWaylandClient; + +namespace xbmc +{ +namespace wayland +{ +class Compositor : + boost::noncopyable +{ +public: + + Compositor(IDllWaylandClient &clientLibrary, + struct wl_compositor *compositor); + ~Compositor(); + + struct wl_compositor * GetWlCompositor(); + + /* Creates a "surface" on the compositor. This is not a renderable + * surface immediately, a renderable "buffer" must be bound to it + * (usually an EGL Window) */ + struct wl_surface * CreateSurface() const; + + /* Creates a "region" on the compositor side. Server side regions + * are manipulated on the client side and then can be used to + * affect rendering and input on the server side */ + struct wl_region * CreateRegion() const; + +private: + + IDllWaylandClient &m_clientLibrary; + struct wl_compositor *m_compositor; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/Display.cpp b/xbmc/windowing/egl/wayland/Display.cpp new file mode 100644 index 0000000000000..52f7c1fdaa66f --- /dev/null +++ b/xbmc/windowing/egl/wayland/Display.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include + +#include + +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Display.h" + +namespace xw = xbmc::wayland; + +void +xw::WaylandDisplayListener::SetHandler(const Handler &handler) +{ + m_handler = handler; +} + +void +xw::WaylandDisplayListener::DisplayAvailable(Display &display) +{ + if (!m_handler.empty()) + m_handler(display); +} + +xw::WaylandDisplayListener & +xw::WaylandDisplayListener::GetInstance() +{ + if (!m_instance) + m_instance.reset(new WaylandDisplayListener()); + + return *m_instance; +} + +boost::scoped_ptr xw::WaylandDisplayListener::m_instance; + +xw::Display::Display(IDllWaylandClient &clientLibrary) : + m_clientLibrary(clientLibrary), + m_display(m_clientLibrary.wl_display_connect(NULL)) +{ + /* wl_display_connect won't throw when it fails, but it does + * return NULL on failure. If this object would be incomplete + * then that is a fatal error for the backend and we should + * throw a runtime_error for the main connection manager to handle + */ + if (!m_display) + { + std::stringstream ss; + ss << "Failed to connect to wayland display"; + throw std::runtime_error(ss.str()); + } + + WaylandDisplayListener::GetInstance().DisplayAvailable(*this); +} + +xw::Display::~Display() +{ + m_clientLibrary.wl_display_flush(m_display); + m_clientLibrary.wl_display_disconnect(m_display); +} + +struct wl_display * +xw::Display::GetWlDisplay() +{ + return m_display; +} + +EGLNativeDisplayType * +xw::Display::GetEGLNativeDisplay() +{ + return &m_display; +} + +/* Create a sync callback object. This can be wrapped in an + * xbmc::wayland::Callback object to call an arbitrary function + * as soon as the display has finished processing all commands. + * + * This does not block until a synchronization is complete - + * consider using a function like WaitForSynchronize to do that */ +struct wl_callback * +xw::Display::Sync() +{ + struct wl_callback *callback = + protocol::CreateWaylandObject (m_clientLibrary, + m_display, + m_clientLibrary.Get_wl_callback_interface()); + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_display, + WL_DISPLAY_SYNC, + callback); + return callback; +} diff --git a/xbmc/windowing/egl/wayland/Display.h b/xbmc/windowing/egl/wayland/Display.h new file mode 100644 index 0000000000000..882d90cde8ecb --- /dev/null +++ b/xbmc/windowing/egl/wayland/Display.h @@ -0,0 +1,75 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +class IDllWaylandClient; + +struct wl_display; +struct wl_callback; + +typedef struct wl_display * EGLNativeDisplayType; + +namespace xbmc +{ +namespace wayland +{ +class Display : + boost::noncopyable +{ + public: + + Display(IDllWaylandClient &clientLibrary); + ~Display(); + + struct wl_display * GetWlDisplay(); + EGLNativeDisplayType* GetEGLNativeDisplay(); + struct wl_callback * Sync(); + + private: + + IDllWaylandClient &m_clientLibrary; + struct wl_display *m_display; +}; + +/* This is effectively just a seam for testing purposes so that + * we can listen for extra objects that the core implementation might + * not necessarily be interested in */ +class WaylandDisplayListener +{ +public: + + typedef boost::function Handler; + + void SetHandler(const Handler &); + void DisplayAvailable(Display &); + + static WaylandDisplayListener & GetInstance(); +private: + + Handler m_handler; + + static boost::scoped_ptr m_instance; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/OpenGLSurface.cpp b/xbmc/windowing/egl/wayland/OpenGLSurface.cpp new file mode 100644 index 0000000000000..551c1df48ff76 --- /dev/null +++ b/xbmc/windowing/egl/wayland/OpenGLSurface.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include "windowing/DllWaylandEgl.h" +#include "OpenGLSurface.h" + +namespace xw = xbmc::wayland; + +xw::OpenGLSurface::OpenGLSurface(IDllWaylandEGL &eglLibrary, + struct wl_surface *surface, + int width, + int height) : + m_eglLibrary(eglLibrary), + m_eglWindow(m_eglLibrary.wl_egl_window_create(surface, + width, + height)) +{ +} + +xw::OpenGLSurface::~OpenGLSurface() +{ + m_eglLibrary.wl_egl_window_destroy(m_eglWindow); +} + +struct wl_egl_window * +xw::OpenGLSurface::GetWlEglWindow() +{ + return m_eglWindow; +} + +EGLNativeWindowType * +xw::OpenGLSurface::GetEGLNativeWindow() +{ + return &m_eglWindow; +} + +void +xw::OpenGLSurface::Resize(int width, int height) +{ + m_eglLibrary.wl_egl_window_resize(m_eglWindow, + width, + height, + 0, + 0); +} diff --git a/xbmc/windowing/egl/wayland/OpenGLSurface.h b/xbmc/windowing/egl/wayland/OpenGLSurface.h new file mode 100644 index 0000000000000..288dbbf1962c1 --- /dev/null +++ b/xbmc/windowing/egl/wayland/OpenGLSurface.h @@ -0,0 +1,56 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +class IDllWaylandEGL; + +struct wl_surface; +struct wl_egl_window; + +typedef struct wl_egl_window * EGLNativeWindowType; + +namespace xbmc +{ +namespace wayland +{ +class OpenGLSurface : + boost::noncopyable +{ +public: + + OpenGLSurface(IDllWaylandEGL &eglLibrary, + struct wl_surface *surface, + int32_t width, + int32_t height); + ~OpenGLSurface(); + + struct wl_egl_window * GetWlEglWindow(); + EGLNativeWindowType * GetEGLNativeWindow(); + void Resize(int width, int height); + +private: + + IDllWaylandEGL &m_eglLibrary; + struct wl_egl_window *m_eglWindow; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/Output.cpp b/xbmc/windowing/egl/wayland/Output.cpp new file mode 100644 index 0000000000000..56bbd3b6cb526 --- /dev/null +++ b/xbmc/windowing/egl/wayland/Output.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Output.h" + +namespace xw = xbmc::wayland; + +/* We only support version 1 of this interface, the other + * struct members are impliedly set to NULL */ +const wl_output_listener xw::Output::m_listener = +{ + Output::GeometryCallback, + Output::ModeCallback +}; + +xw::Output::Output(IDllWaylandClient &clientLibrary, + struct wl_output *output) : + m_clientLibrary(clientLibrary), + m_output(output), + m_scaleFactor(1.0), + m_currentValid(false), + m_preferredValid(false) +{ + protocol::AddListenerOnWaylandObject(m_clientLibrary, + m_output, + &m_listener, + reinterpret_cast(this)); +} + +xw::Output::~Output() +{ + protocol::DestroyWaylandObject(m_clientLibrary, + m_output); +} + +struct wl_output * +xw::Output::GetWlOutput() +{ + return m_output; +} + +/* It is a precondition violation to use CurrentMode() and + * PreferredMode() before output modes have arrived yet, use + * a synchronization function to ensure that this is the case */ +const xw::Output::ModeGeometry & +xw::Output::CurrentMode() +{ + if (!m_currentValid) + throw std::logic_error("No current mode has been set by the server" + " yet"); + + return m_current; +} + +const xw::Output::ModeGeometry & +xw::Output::PreferredMode() +{ + if (!m_preferredValid) + throw std::logic_error("No preferred mode has been set by the " + " server yet"); + + return m_preferred; +} + +const std::vector & +xw::Output::AllModes() +{ + return m_modes; +} + +const xw::Output::PhysicalGeometry & +xw::Output::Geometry() +{ + return m_geometry; +} + +uint32_t +xw::Output::ScaleFactor() +{ + return m_scaleFactor; +} + +void +xw::Output::GeometryCallback(void *data, + struct wl_output *output, + int32_t x, + int32_t y, + int32_t physicalWidth, + int32_t physicalHeight, + int32_t subpixelArrangement, + const char *make, + const char *model, + int32_t transform) +{ + return static_cast(data)->Geometry(x, + y, + physicalWidth, + physicalHeight, + subpixelArrangement, + make, + model, + transform); +} + +void +xw::Output::ModeCallback(void *data, + struct wl_output *output, + uint32_t flags, + int32_t width, + int32_t height, + int32_t refresh) +{ + return static_cast(data)->Mode(flags, + width, + height, + refresh); +} + +void +xw::Output::DoneCallback(void *data, + struct wl_output *output) +{ + return static_cast(data)->Done(); +} + +void +xw::Output::ScaleCallback(void *data, + struct wl_output *output, + int32_t factor) +{ + return static_cast(data)->Scale(factor); +} + +/* This function is called when the output geometry is determined. + * + * The output geometry represents the actual geometry of the monitor. + * As it is per-output, there is only one geometry. + */ +void +xw::Output::Geometry(int32_t x, + int32_t y, + int32_t physicalWidth, + int32_t physicalHeight, + int32_t subpixelArrangement, + const char *make, + const char *model, + int32_t transform) +{ + m_geometry.x = x; + m_geometry.y = y; + m_geometry.physicalWidth = physicalWidth; + m_geometry.physicalHeight = physicalHeight; + m_geometry.subpixelArrangement = + static_cast(subpixelArrangement); + m_geometry.outputTransformation = + static_cast(transform); +} + +/* This function is called when a new mode is available on this output + * or a mode's state changes. + * + * It is possible that the same mode can change its state, so we will + * not add it twice. Instead, we will determine if the mode is the + * same one, but its flags have been updated and if so, update + * the pointers to modes having those flags. + */ +void +xw::Output::Mode(uint32_t flags, + int32_t width, + int32_t height, + int32_t refresh) +{ + xw::Output::ModeGeometry *update = NULL; + + for (std::vector::iterator it = m_modes.begin(); + it != m_modes.end(); + ++it) + { + if (it->width == width && + it->height == height && + it->refresh == refresh) + { + update = &(*it); + break; + } + } + + enum wl_output_mode outputFlags = + static_cast(flags); + + if (!update) + { + /* New output created */ + m_modes.push_back(ModeGeometry()); + ModeGeometry &next(m_modes.back()); + + next.width = width; + next.height = height; + next.refresh = refresh; + + update = &next; + } + + /* We may get a mode notification for a new or + * or existing mode. In both cases we need to + * update the current and preferred modes */ + if (outputFlags & WL_OUTPUT_MODE_CURRENT) + { + m_current = *update; + m_currentValid = true; + } + if (outputFlags & WL_OUTPUT_MODE_PREFERRED) + { + m_preferred = *update; + m_preferredValid = true; + } +} + +void +xw::Output::Done() +{ +} + +/* This function is called whenever the scaling factor for this + * output changes. It there for clients to support HiDPI displays, + * although unused as of present */ +void +xw::Output::Scale(int32_t factor) +{ + m_scaleFactor = factor; +} diff --git a/xbmc/windowing/egl/wayland/Output.h b/xbmc/windowing/egl/wayland/Output.h new file mode 100644 index 0000000000000..9743b68b224fb --- /dev/null +++ b/xbmc/windowing/egl/wayland/Output.h @@ -0,0 +1,152 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +#include + +class IDllWaylandClient; + +namespace xbmc +{ +namespace wayland +{ +struct Output : + boost::noncopyable +{ +public: + + Output(IDllWaylandClient &, + struct wl_output *); + ~Output(); + + struct ModeGeometry + { + int32_t width; + int32_t height; + int32_t refresh; + }; + + struct PhysicalGeometry + { + int32_t x; + int32_t y; + int32_t physicalWidth; + int32_t physicalHeight; + enum wl_output_subpixel subpixelArrangement; + enum wl_output_transform outputTransformation; + }; + + struct wl_output * GetWlOutput(); + + /* It is a precondition violation to use the following four + * functions when the first modes have not yet been received. + * + * Use a synchronization point after creating this object + * (eg, WaitForSynchronize() to ensure that the initial modes + * are available */ + + /* The "current" mode is the mode that the display is currently + * using */ + const ModeGeometry & CurrentMode(); + + /* The "preferred" mode is the mode most optimal to this output. + * + * This is usually the maximum possible mode that this output + * supports. All fullscreen windows should generally have a buffer + * of this size in order to avoid scaling. */ + const ModeGeometry & PreferredMode(); + + const std::vector & AllModes(); + + /* The geometry represents the physical geometry of this monitor */ + const PhysicalGeometry & Geometry(); + + /* The scale factor of this output is an integer value representing + * the number of output pixels per hardware pixel. For instance, + * if UI elements were scaled up to 1680x1050 and the monitor was + * displaying at a native resolution of 3360x2100 when this would be + * "2". This is useful for supporting HiDPI display modes where, + * for instance we allocate a 3360x2100 buffer but display our UI + * elements at 1680x1050 */ + uint32_t ScaleFactor(); + + static void GeometryCallback(void *, + struct wl_output *, + int32_t, + int32_t, + int32_t, + int32_t, + int32_t, + const char *, + const char *, + int32_t); + static void ModeCallback(void *, + struct wl_output *, + uint32_t, + int32_t, + int32_t, + int32_t); + static void ScaleCallback(void *, + struct wl_output *, + int32_t); + static void DoneCallback(void *, + struct wl_output *); + +private: + + static const wl_output_listener m_listener; + + void Geometry(int32_t x, + int32_t y, + int32_t physicalWidth, + int32_t physicalHeight, + int32_t subpixel, + const char *make, + const char *model, + int32_t transform); + void Mode(uint32_t flags, + int32_t width, + int32_t height, + int32_t refresh); + void Scale(int32_t); + void Done(); + + IDllWaylandClient &m_clientLibrary; + + struct wl_output *m_output; + + PhysicalGeometry m_geometry; + std::vector m_modes; + + uint32_t m_scaleFactor; + + /* Only one mode at a time can have the current or preferred + * flags set, so only one pointer is set here */ + ModeGeometry m_current; + ModeGeometry m_preferred; + bool m_currentValid; + bool m_preferredValid; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/Region.cpp b/xbmc/windowing/egl/wayland/Region.cpp new file mode 100644 index 0000000000000..62aed1b601206 --- /dev/null +++ b/xbmc/windowing/egl/wayland/Region.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Region.h" + +namespace xw = xbmc::wayland; + +xw::Region::Region(IDllWaylandClient &clientLibrary, + struct wl_region *region) : + m_clientLibrary(clientLibrary), + m_region(region) +{ +} + +xw::Region::~Region() +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_region, + WL_REGION_DESTROY); + protocol::DestroyWaylandObject(m_clientLibrary, + m_region); +} + +struct wl_region * +xw::Region::GetWlRegion() +{ + return m_region; +} + +void +xw::Region::AddRectangle(int32_t x, + int32_t y, + int32_t width, + int32_t height) +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_region, + WL_REGION_ADD, + x, + y, + width, + height); +} diff --git a/xbmc/windowing/egl/wayland/Region.h b/xbmc/windowing/egl/wayland/Region.h new file mode 100644 index 0000000000000..d9ec1497831da --- /dev/null +++ b/xbmc/windowing/egl/wayland/Region.h @@ -0,0 +1,54 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +class IDllWaylandClient; + +struct wl_region; + +namespace xbmc +{ +namespace wayland +{ +class Region : + boost::noncopyable +{ +public: + + Region(IDllWaylandClient &clientLibrary, + struct wl_region *); + ~Region(); + + struct wl_region * GetWlRegion(); + + void AddRectangle(int32_t x, + int32_t y, + int32_t width, + int32_t height); + +private: + + IDllWaylandClient &m_clientLibrary; + struct wl_region *m_region; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/Registry.cpp b/xbmc/windowing/egl/wayland/Registry.cpp new file mode 100644 index 0000000000000..2a433f3526e2b --- /dev/null +++ b/xbmc/windowing/egl/wayland/Registry.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Registry.h" + +namespace xw = xbmc::wayland; + +const struct wl_registry_listener xw::Registry::m_listener = +{ + Registry::HandleGlobalCallback, + Registry::HandleRemoveGlobalCallback +}; + +/* Only one observer may be registered at a time */ +void +xw::ExtraWaylandGlobals::SetHandler(const GlobalHandler &handler) +{ + m_handler = handler; +} + +void +xw::ExtraWaylandGlobals::NewGlobal(struct wl_registry *registry, + uint32_t name, + const char *interface, + uint32_t version) +{ + if (!m_handler.empty()) + m_handler(registry, name, interface, version); +} + +xw::ExtraWaylandGlobals & +xw::ExtraWaylandGlobals::GetInstance() +{ + if (!m_instance) + m_instance.reset(new ExtraWaylandGlobals()); + + return *m_instance; +} + +boost::scoped_ptr xw::ExtraWaylandGlobals::m_instance; + +/* We inject an IWaylandRegistration here which is a virtual + * class which a callback for the global objects + * used by xbmc. Once one of those objects becomes + * available, we call the callback function on that + * interface. If it returns false, then it means that the main + * xbmc implementation isn't interested in that object, so we + * call out to a listener that can be bound to by any client code + * (as it is a singleton) to see if that code is interested + * in the interface and wants to bind to it. This is particularly + * useful for testing purposes where custom objects on the compositor + * side are used. */ +xw::Registry::Registry(IDllWaylandClient &clientLibrary, + struct wl_display *display, + IWaylandRegistration ®istration) : + m_clientLibrary(clientLibrary), + m_registry(protocol::CreateWaylandObject (m_clientLibrary, + display, + m_clientLibrary.Get_wl_registry_interface())), + m_registration(registration) +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + display, + WL_DISPLAY_GET_REGISTRY, + m_registry); + protocol::AddListenerOnWaylandObject(m_clientLibrary, + m_registry, + &m_listener, + reinterpret_cast(this)); +} + +xw::Registry::~Registry() +{ + protocol::DestroyWaylandObject(m_clientLibrary, m_registry); +} + +/* Once a global becomes available, we immediately bind to it here + * and then notify the injected listener interface that the global + * is available on a named object. This allows that interface to + * respond to the arrival of the new global how it wishes */ +void +xw::Registry::BindInternal(uint32_t name, + const char *interface, + uint32_t version, + void *proxy) +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_registry, + WL_REGISTRY_BIND, + name, + interface, + version, + proxy); +} + +void +xw::Registry::HandleGlobal(uint32_t name, + const char *interface, + uint32_t version) +{ + /* Check if our injected listener wants to know about this - + * otherwise let any external listeners know */ + if (!m_registration.OnGlobalInterfaceAvailable(name, + interface, + version)) + { + ExtraWaylandGlobals::GetInstance().NewGlobal(m_registry, + name, + interface, + version); + } +} + +void +xw::Registry::HandleRemoveGlobal(uint32_t name) +{ +} + +void +xw::Registry::HandleGlobalCallback(void *data, + struct wl_registry *registry, + uint32_t name, + const char *interface, + uint32_t version) +{ + static_cast(data)->HandleGlobal(name, interface, version); +} + +void +xw::Registry::HandleRemoveGlobalCallback(void *data, + struct wl_registry *registry, + uint32_t name) +{ + static_cast(data)->HandleRemoveGlobal(name); +} diff --git a/xbmc/windowing/egl/wayland/Registry.h b/xbmc/windowing/egl/wayland/Registry.h new file mode 100644 index 0000000000000..61ce455c45e79 --- /dev/null +++ b/xbmc/windowing/egl/wayland/Registry.h @@ -0,0 +1,130 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include +#include +#include + +#include + +#include "windowing/WaylandProtocol.h" + +class IDllWaylandClient; + +namespace xbmc +{ +namespace wayland +{ +/* This is effectively just a seam for testing purposes so that + * we can listen for extra objects that the core implementation might + * not necessarily be interested in */ +class ExtraWaylandGlobals +{ +public: + + typedef boost::function GlobalHandler; + + void SetHandler(const GlobalHandler &); + void NewGlobal(struct wl_registry *, + uint32_t, + const char *, + uint32_t); + + static ExtraWaylandGlobals & GetInstance(); +private: + + GlobalHandler m_handler; + + static boost::scoped_ptr m_instance; +}; + +class IWaylandRegistration +{ +public: + + virtual ~IWaylandRegistration() {}; + + virtual bool OnGlobalInterfaceAvailable(uint32_t, + const char *, + uint32_t) = 0; +}; + +class Registry : + boost::noncopyable +{ +public: + + Registry(IDllWaylandClient &clientLibrary, + struct wl_display *display, + IWaylandRegistration ®istration); + ~Registry(); + + struct wl_registry * GetWlRegistry(); + + template + Create Bind(uint32_t name, + struct wl_interface **interface, + uint32_t version) + { + Create object = + protocol::CreateWaylandObject(m_clientLibrary, + m_registry, + interface); + + /* This looks a bit funky - but it is correct. The dll returns + * a ** to wl_interface when it is in fact just a pointer to + * the static variable, so we need to remove one indirection */ + BindInternal(name, + reinterpret_cast(interface)->name, + version, + object); + return object; + } + +private: + + static const struct wl_registry_listener m_listener; + + static void HandleGlobalCallback(void *, struct wl_registry *, + uint32_t, const char *, uint32_t); + static void HandleRemoveGlobalCallback(void *, struct wl_registry *, + uint32_t name); + + void BindInternal(uint32_t name, + const char *interface, + uint32_t version, + void *proxy); + + IDllWaylandClient &m_clientLibrary; + struct wl_registry *m_registry; + IWaylandRegistration &m_registration; + + void HandleGlobal(uint32_t, const char *, uint32_t); + void HandleRemoveGlobal(uint32_t); +}; +} +} diff --git a/xbmc/windowing/egl/wayland/Shell.cpp b/xbmc/windowing/egl/wayland/Shell.cpp new file mode 100644 index 0000000000000..cdc9bad09ab7c --- /dev/null +++ b/xbmc/windowing/egl/wayland/Shell.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Shell.h" + +namespace xw = xbmc::wayland; + +xw::Shell::Shell(IDllWaylandClient &clientLibrary, + struct wl_shell *shell) : + m_clientLibrary(clientLibrary), + m_shell(shell) +{ +} + +xw::Shell::~Shell() +{ + protocol::DestroyWaylandObject(m_clientLibrary, + m_shell); +} + +struct wl_shell * +xw::Shell::GetWlShell() +{ + return m_shell; +} + +struct wl_shell_surface * +xw::Shell::CreateShellSurface(struct wl_surface *surface) +{ + struct wl_shell_surface *shellSurface = + protocol::CreateWaylandObject(m_clientLibrary, + m_shell, + m_clientLibrary.Get_wl_shell_surface_interface ()); + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_shell, + WL_SHELL_GET_SHELL_SURFACE, + shellSurface, + surface); + return shellSurface; +} diff --git a/xbmc/windowing/egl/wayland/Shell.h b/xbmc/windowing/egl/wayland/Shell.h new file mode 100644 index 0000000000000..4e5c19ce1e9db --- /dev/null +++ b/xbmc/windowing/egl/wayland/Shell.h @@ -0,0 +1,52 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +class IDllWaylandClient; + +struct wl_shell; +struct wl_shell_surface; +struct wl_surface; + +namespace xbmc +{ +namespace wayland +{ +class Shell : + boost::noncopyable +{ +public: + + Shell(IDllWaylandClient &clientLibrary, + struct wl_shell *shell); + ~Shell(); + + struct wl_shell * GetWlShell(); + struct wl_shell_surface * CreateShellSurface(struct wl_surface *); + +private: + + IDllWaylandClient &m_clientLibrary; + struct wl_shell *m_shell; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/ShellSurface.cpp b/xbmc/windowing/egl/wayland/ShellSurface.cpp new file mode 100644 index 0000000000000..a4070c8e23b2d --- /dev/null +++ b/xbmc/windowing/egl/wayland/ShellSurface.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "ShellSurface.h" + +namespace xw = xbmc::wayland; + +const wl_shell_surface_listener xw::ShellSurface::m_listener = +{ + ShellSurface::HandlePingCallback, + ShellSurface::HandleConfigureCallback, + ShellSurface::HandlePopupDoneCallback +}; + +xw::ShellSurface::ShellSurface(IDllWaylandClient &clientLibrary, + struct wl_shell_surface *shell_surface) : + m_clientLibrary(clientLibrary), + m_shellSurface(shell_surface) +{ + protocol::AddListenerOnWaylandObject(m_clientLibrary, + m_shellSurface, + &m_listener, + reinterpret_cast(this)); +} + +xw::ShellSurface::~ShellSurface() +{ + protocol::DestroyWaylandObject(m_clientLibrary, m_shellSurface); +} + +struct wl_shell_surface * +xw::ShellSurface::GetWlShellSurface() +{ + return m_shellSurface; +} + +void +xw::ShellSurface::SetFullscreen(enum wl_shell_surface_fullscreen_method method, + uint32_t framerate, + struct wl_output *output) +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_shellSurface, + WL_SHELL_SURFACE_SET_FULLSCREEN, + method, + framerate, + output); +} + +void +xw::ShellSurface::HandlePingCallback(void *data, + struct wl_shell_surface *shell_surface, + uint32_t serial) +{ + return static_cast(data)->HandlePing(serial); +} + +void +xw::ShellSurface::HandleConfigureCallback(void *data, + struct wl_shell_surface *shell_surface, + uint32_t edges, + int32_t width, + int32_t height) +{ + return static_cast(data)->HandleConfigure(edges, + width, + height); +} + +void +xw::ShellSurface::HandlePopupDoneCallback(void *data, + struct wl_shell_surface *shell_surface) +{ + return static_cast(data)->HandlePopupDone(); +} + +void +xw::ShellSurface::HandlePing(uint32_t serial) +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_shellSurface, + WL_SHELL_SURFACE_PONG, + serial); +} + +void +xw::ShellSurface::HandleConfigure(uint32_t edges, + int32_t width, + int32_t height) +{ +} + +void +xw::ShellSurface::HandlePopupDone() +{ +} diff --git a/xbmc/windowing/egl/wayland/ShellSurface.h b/xbmc/windowing/egl/wayland/ShellSurface.h new file mode 100644 index 0000000000000..eeadd41466d64 --- /dev/null +++ b/xbmc/windowing/egl/wayland/ShellSurface.h @@ -0,0 +1,71 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +class IDllWaylandClient; + +namespace xbmc +{ +namespace wayland +{ +class ShellSurface : + boost::noncopyable +{ +public: + + ShellSurface(IDllWaylandClient &clientLibrary, + struct wl_shell_surface *shellSurface); + ~ShellSurface(); + + struct wl_shell_surface * GetWlShellSurface(); + void SetFullscreen(enum wl_shell_surface_fullscreen_method method, + uint32_t framerate, + struct wl_output *output); + + static const wl_shell_surface_listener m_listener; + + static void HandlePingCallback(void *, + struct wl_shell_surface *, + uint32_t); + static void HandleConfigureCallback(void *, + struct wl_shell_surface *, + uint32_t, + int32_t, + int32_t); + static void HandlePopupDoneCallback(void *, + struct wl_shell_surface *); + +private: + + void HandlePing(uint32_t serial); + void HandleConfigure(uint32_t edges, + int32_t width, + int32_t height); + void HandlePopupDone(); + + IDllWaylandClient &m_clientLibrary; + struct wl_shell_surface *m_shellSurface; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/Surface.cpp b/xbmc/windowing/egl/wayland/Surface.cpp new file mode 100644 index 0000000000000..9e787c75c8cd6 --- /dev/null +++ b/xbmc/windowing/egl/wayland/Surface.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Surface.h" + +namespace xw = xbmc::wayland; + +boost::scoped_ptr xw::WaylandSurfaceListener::m_instance; + +xw::WaylandSurfaceListener & +xw::WaylandSurfaceListener::GetInstance() +{ + if (!m_instance) + m_instance.reset(new WaylandSurfaceListener()); + + return *m_instance; +} + +void +xw::WaylandSurfaceListener::SetHandler(const Handler &handler) +{ + m_handler = handler; +} + +void +xw::WaylandSurfaceListener::SurfaceCreated(xw::Surface &surface) +{ + if (!m_handler.empty()) + m_handler(surface); +} + +xw::Surface::Surface(IDllWaylandClient &clientLibrary, + struct wl_surface *surface) : + m_clientLibrary(clientLibrary), + m_surface(surface) +{ + WaylandSurfaceListener::GetInstance().SurfaceCreated(*this); +} + +xw::Surface::~Surface() +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_surface, + WL_SURFACE_DESTROY); + protocol::DestroyWaylandObject(m_clientLibrary, + m_surface); +} + +struct wl_surface * +xw::Surface::GetWlSurface() +{ + return m_surface; +} + +struct wl_callback * +xw::Surface::CreateFrameCallback() +{ + struct wl_callback *callback = + protocol::CreateWaylandObject(m_clientLibrary, + m_surface, + m_clientLibrary.Get_wl_callback_interface()); + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_surface, + WL_SURFACE_FRAME, callback); + return callback; +} + +void +xw::Surface::SetOpaqueRegion(struct wl_region *region) +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_surface, + WL_SURFACE_SET_OPAQUE_REGION, + region); +} + +void +xw::Surface::Commit() +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_surface, + WL_SURFACE_COMMIT); +} diff --git a/xbmc/windowing/egl/wayland/Surface.h b/xbmc/windowing/egl/wayland/Surface.h new file mode 100644 index 0000000000000..358978d324976 --- /dev/null +++ b/xbmc/windowing/egl/wayland/Surface.h @@ -0,0 +1,78 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +struct wl_surface; +struct wl_callback; +struct wl_region; + +class IDllWaylandClient; + +namespace xbmc +{ +namespace wayland +{ +class Surface : + boost::noncopyable +{ +public: + + Surface(IDllWaylandClient &clientLibrary, + struct wl_surface *surface); + ~Surface(); + + struct wl_surface * GetWlSurface(); + struct wl_callback * CreateFrameCallback(); + void SetOpaqueRegion(struct wl_region *region); + void Commit(); + +private: + + IDllWaylandClient &m_clientLibrary; + struct wl_surface *m_surface; +}; + +/* This is effectively just a seam for testing purposes so that + * we can listen for extra objects that the core implementation might + * not necessarily be interested in. It isn't possible to get any + * notification from within weston that a surface was created so + * we need to rely on the client side in order to do that */ +class WaylandSurfaceListener +{ +public: + + typedef boost::function Handler; + + void SetHandler(const Handler &); + void SurfaceCreated(Surface &); + + static WaylandSurfaceListener & GetInstance(); +private: + + Handler m_handler; + + static boost::scoped_ptr m_instance; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/WaylandLibraries.cpp b/xbmc/windowing/egl/wayland/WaylandLibraries.cpp new file mode 100644 index 0000000000000..5562635808ce6 --- /dev/null +++ b/xbmc/windowing/egl/wayland/WaylandLibraries.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include +#include "WaylandLibraries.h" + +namespace xw = xbmc::wayland; + +void +xw::LoadLibrary(DllDynamic &dll) +{ + if (!dll.Load()) + { + std::stringstream ss; + ss << "Failed to load library " + << dll.GetFile().c_str(); + + throw std::runtime_error(ss.str()); + } +} + +IDllWaylandClient & +xw::Libraries::ClientLibrary() +{ + return m_clientLibrary.Get(); +} + +IDllWaylandEGL & +xw::Libraries::EGLLibrary() +{ + return m_eglLibrary.Get(); +} + +IDllXKBCommon & +xw::Libraries::XKBCommonLibrary() +{ + return m_xkbCommonLibrary.Get(); +} diff --git a/xbmc/windowing/egl/wayland/WaylandLibraries.h b/xbmc/windowing/egl/wayland/WaylandLibraries.h new file mode 100644 index 0000000000000..3c7193d869be2 --- /dev/null +++ b/xbmc/windowing/egl/wayland/WaylandLibraries.h @@ -0,0 +1,84 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/DllWaylandEgl.h" +#include "windowing/DllXKBCommon.h" + +namespace xbmc +{ +namespace wayland +{ +template +class AutoloadDll : + boost::noncopyable +{ + public: + + AutoloadDll(); + ~AutoloadDll(); + DllInterface & Get(); + + private: + + Dll m_dll; +}; + +class Libraries : + boost::noncopyable +{ +public: + + IDllWaylandClient & ClientLibrary(); + IDllWaylandEGL & EGLLibrary(); + IDllXKBCommon & XKBCommonLibrary(); + +private: + + AutoloadDll m_clientLibrary; + AutoloadDll m_eglLibrary; + AutoloadDll m_xkbCommonLibrary; +}; + +void LoadLibrary(DllDynamic &dll); + +template +AutoloadDll::AutoloadDll() +{ + LoadLibrary(m_dll); +} + +template +DllInterface & +AutoloadDll::Get() +{ + return m_dll; +} + +template +AutoloadDll::~AutoloadDll() +{ + m_dll.Unload(); +} +} +} diff --git a/xbmc/windowing/egl/wayland/XBMCConnection.cpp b/xbmc/windowing/egl/wayland/XBMCConnection.cpp new file mode 100644 index 0000000000000..7b1b4672afd27 --- /dev/null +++ b/xbmc/windowing/egl/wayland/XBMCConnection.cpp @@ -0,0 +1,763 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "guilib/Resolution.h" +#include "guilib/gui3d.h" + +#include "utils/StringUtils.h" + +#include "windowing/DllWaylandClient.h" +#include "windowing/DllXKBCommon.h" + +#include "Callback.h" +#include "Compositor.h" +#include "Display.h" +#include "Output.h" +#include "Registry.h" +#include "Region.h" +#include "Shell.h" + +#include "windowing/WaylandProtocol.h" +#include "XBMCConnection.h" + +#include "windowing/wayland/Wayland11EventQueueStrategy.h" +#include "windowing/wayland/Wayland12EventQueueStrategy.h" + +namespace xbmc +{ +namespace wayland +{ +/* A RemoteGlobalInterface just describes a pure virtual class + * which is an observer for Private::OnGlobalInterfaceAvailable + * when a new global interface appears on the compositor for the + * client to bind to */ +class RemoteGlobalInterface +{ +public: + + virtual ~RemoteGlobalInterface() {} + + struct Constructor + { + const char *interfaceName; + RemoteGlobalInterface *interface; + }; + + virtual void OnObjectAvailable(uint32_t name, uint32_t version) = 0; +}; + +/* A GlobalInterface is a simple implementation of a + * RemoteGlobalInterface with OnObjectAvailable already implemented. + * + * Users of this class are able to inject a custom function to be + * observe whenever an object becomes avilable to this class and can + * get a queue of all names available for the particular interface + * this class is asked to observe. The object name is effectively + * just a number referring to the global object ID on the compositor + * side that can be bound to by a client. */ +class GlobalInterface : + public RemoteGlobalInterface +{ +public: + + typedef boost::function AvailabilityHook; + +protected: + + GlobalInterface(const AvailabilityHook &hook) : + m_hook(hook) + { + } + + GlobalInterface() + { + } + + std::queue & ObjectsAvailable(uint32_t minimum); + +private: + + virtual void OnObjectAvailable(uint32_t name, uint32_t version); + + std::queue m_availableNames; + uint32_t m_version; + AvailabilityHook m_hook; +}; + +/* A WaylandGlobalObject is a more complete implementation of + * GlobalInterface. It observes for when objects become available + * and provides a method to fetch-and-bind names on-demand. + * + * Once FetchPending is called, the name is removed from the pending + * queue of GlobalInterface, bound to the interface provided and + * returned as an Implementation */ +template +class WaylandGlobalObject : + public GlobalInterface +{ +public: + + WaylandGlobalObject(uint32_t minimum, + struct wl_interface **interface) : + GlobalInterface(), + m_minimum(minimum), + m_interface(interface) + { + } + + WaylandGlobalObject(uint32_t minimum, + struct wl_interface **interface, + const AvailabilityHook &hook) : + GlobalInterface(hook), + m_minimum(minimum), + m_interface(interface) + { + } + + Implementation * FetchPending(Registry ®istry); + +private: + + uint32_t m_minimum; + struct wl_interface **m_interface; +}; + +/* A StoredGlobalInterface is an implementation of RemoteGlobalInterface + * which composes a WaylandGlobalObject internally. + * + * This class takes a factory function to produce an Implementation * + * (usually a wrapper class of some sort) from a WaylandImplementation * + * (usually the defined wayland proxy object in the autogenerated + * protocol). It also has an alternate constructor that allows + * outside users to observe when an object has initially become available + * which is useful if it needs to be registered right away. + */ +template +class StoredGlobalInterface : + public RemoteGlobalInterface +{ +public: + + typedef boost::function Factory; + typedef std::vector > Implementations; + + /* Factory must be capable of returning a new Implementation * + * corresponding to a WaylandImplementation *. This is usually + * a wrapper class around that wayland object */ + StoredGlobalInterface(const Factory &factory, + uint32_t minimum, + struct wl_interface **interface) : + m_waylandObject(minimum, interface), + m_factory(factory) + { + } + + StoredGlobalInterface(const Factory &factory, + uint32_t minimum, + struct wl_interface **interface, + const GlobalInterface::AvailabilityHook &hook) : + m_waylandObject(minimum, interface, hook), + m_factory(factory) + { + } + + ~StoredGlobalInterface() + { + } + + /* These two functions always return constant values, although + * they might be required to create new Implementation objects + * by binding a global wayland object and wrapping it when they + * are initially called. + * + * The first function always returns the first-available interface, + * the second function always returns the list of available global + * objects which have that interface */ + Implementation & GetFirst(Registry ®istry); + Implementations & Get(Registry ®istry); + +private: + + void OnObjectAvailable(uint32_t name, + uint32_t version); + + WaylandGlobalObject m_waylandObject; + Factory m_factory; + Implementations m_implementations; +}; + +class XBMCConnection::Private : + public IWaylandRegistration +{ +public: + + Private(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + EventInjector &eventInjector); + ~Private(); + + /* Synchronization entry point - call this function to issue a + * wl_display.sync request to the server. All this does is cause + * the server to send back an event that acknowledges the receipt + * of the request. However, it is useful in a number of circumstances + * - all request processing in wayland is sequential and guarunteed + * to be in the same order as requests were made. That means that + * once the event is received from the server, it is guarunteed + * that all requests made prior to the sync request have finished + * processing on the server and events have been issued to us. + * + * Do not call this from a non-main thread. The main thread may be + * waiting for a wl_display.sync event to be coming through and this + * function will merely spin until synchronized == true, for which + * a non-main thread may be responsible for setting as true */ + void WaitForSynchronize(); + + wayland::Display & Display(); + wayland::Compositor & Compositor(); + wayland::Shell & Shell(); + wayland::Output & Output(); + +private: + + IDllWaylandClient &m_clientLibrary; + IDllXKBCommon &m_xkbCommonLibrary; + + EventInjector m_eventInjector; + + /* Do not call this from a non-main thread. The main thread may be + * waiting for a wl_display.sync event to be coming through and this + * function will merely spin until synchronized == true, for which + * a non-main thread may be responsible for setting as true */ + void Synchronize(); + + /* Synchronization logic - these variables should not be touched + * outside the scope of WaitForSynchronize() */ + bool synchronized; + boost::scoped_ptr synchronizeCallback; + + bool OnGlobalInterfaceAvailable(uint32_t name, + const char *interface, + uint32_t version); + + void InjectSeat(); + + boost::scoped_ptr m_display; + boost::scoped_ptr m_registry; + + StoredGlobalInterface m_compositor; + StoredGlobalInterface m_shell; + WaylandGlobalObject m_seat; + StoredGlobalInterface m_outputs; + + boost::scoped_ptr m_eventQueue; +}; +} +} + +namespace xw = xbmc::wayland; +namespace xwe = xbmc::wayland::events; +namespace xwe = xbmc::wayland::events; + +void +xw::GlobalInterface::OnObjectAvailable(uint32_t name, + uint32_t version) +{ + m_availableNames.push(name); + m_version = version; + + if (!m_hook.empty()) + m_hook(m_version); +} + +std::queue & +xw::GlobalInterface::ObjectsAvailable(uint32_t minimum) +{ + if (m_version < minimum) + { + std::stringstream ss; + ss << "Interface version at least " + << minimum + << " is not available" + << " (less than version: " + << m_version + << ")"; + throw std::runtime_error(ss.str()); + } + + return m_availableNames; +} + +template +Implementation * +xw::WaylandGlobalObject::FetchPending(Registry ®istry) +{ + /* Pop any new names and bind them */ + std::queue &availableObjects(ObjectsAvailable(m_minimum)); + if (!availableObjects.empty()) + { + uint32_t name = availableObjects.front(); + Implementation *proxy = + registry.Bind(name, + m_interface, + m_minimum); + availableObjects.pop(); + return proxy; + } + + return NULL; +} + +template +void +xw::StoredGlobalInterface::OnObjectAvailable(uint32_t name, uint32_t version) +{ + RemoteGlobalInterface &rgi = + static_cast(m_waylandObject); + rgi.OnObjectAvailable(name, version); +} + +template +typename xw::StoredGlobalInterface::Implementations & +xw::StoredGlobalInterface::Get(Registry ®istry) +{ + /* Instantiate any pending objects with this interface and then + * return the available implementations */ + WaylandImplementation *proxy = + m_waylandObject.FetchPending(registry); + + while (proxy) + { + boost::shared_ptr instance(m_factory(proxy)); + m_implementations.push_back(instance); + proxy = m_waylandObject.FetchPending(registry); + } + + /* Calling Get() before we've received any notification that + * objects are available is a runtime_error and will be thrown as + * such. + * + * Calling code that wishes to avoid this error should either + * insert a synchronization point right after creating the object + * registry or register a callback using the second constructor + * to observe when the object has become available before calling + * Get(). */ + if (m_implementations.empty()) + throw std::runtime_error("Remote interface not available"); + + return m_implementations; +} + +template +Implementation & +xw::StoredGlobalInterface::GetFirst(xw::Registry ®istry) +{ + return *(Get(registry)[0]); +} + +namespace +{ +const std::string CompositorName("wl_compositor"); +const std::string ShellName("wl_shell"); +const std::string SeatName("wl_seat"); +const std::string OutputName("wl_output"); + +/* These are functions that satisfy the definition of a "Factory" + * for the purposes of StoredGlobalInterface */ +xw::Compositor * CreateCompositor(struct wl_compositor *compositor, + IDllWaylandClient *clientLibrary) +{ + return new xw::Compositor(*clientLibrary, compositor); +} + +xw::Output * CreateOutput(struct wl_output *output, + IDllWaylandClient *clientLibrary) +{ + return new xw::Output(*clientLibrary, output); +} + +xw::Shell * CreateShell(struct wl_shell *shell, + IDllWaylandClient *clientLibrary) +{ + return new xw::Shell(*clientLibrary, shell); +} + +bool ConstructorMatchesInterface(const xw::RemoteGlobalInterface::Constructor &constructor, + const char *interface) +{ + return std::strcmp(constructor.interfaceName, + interface) < 0; +} + +const unsigned int RequestedCompositorVersion = 1; +const unsigned int RequestedShellVersion = 1; +const unsigned int RequestedOutputVersion = 1; +const unsigned int RequestedSeatVersion = 1; + +/* A deficiency in the client library in wayland versions prior to + * 1.2 means that there is divergent behaviour between versions here + * and this is explicitly expressed and encapsulated in these two + * strategies. + * + * Because xbmc uses a game-loop, it is expected that no operation + * should block the main thread. This includes any operations to + * read the window system event queue. The main thread might be blocked + * for a prolonged period in the situation where the main xbmc surface + * is not visible, because the screen lock is active or another + * surface is obstructing it. When the main thread becomes blocked, + * it means that xbmc isn't able to start or stop any background jobs, + * which could interrupt library updates which occurr on idle or + * other such operations. + * + * However, wayland versions prior to 1.2 had the expectation that + * clients expected to block if there were no incoming compositor + * events because it is part of wayland's design that the compositor + * is responsible for sending the events to drive a client's render + * and input loop. As such, on wayland <= 1.1, the expectation is that + * compositor event read and dispatch occurrs in the same thread and + * on wayland >= 1.2 the expectation is that these operations can + * occurr in multiple threads. + * + * The following table illustrates these differences: + * + * --------------------------------------------------------------------- + * | Wayland | Thread that | Thread that | Thread that | Strategy | + * | Version | Reads happen | wrappers | flush happens | Object | + * | | in | operate in | | | + * | | | in | | | + * --------------------------------------------------------------------- + * | <= 1.1 | Poll Thread | Poll Thread | Main Thread | xw::versio-| + * | | | | | n11::Event-| + * | | | | | QueueStrat-| + * | | | | | egy | + * --------------------------------------------------------------------- + * | >= 1.2 | Poll Thread | Main Thread | Main Thread | xw::versio-| + * | | | | | n12::Event-| + * | | | | | QueueStrat-| + * | | | | | egy | + * --------------------------------------------------------------------- + * + * The reason why it is different between the two versions it that it + * is generally desirable that the operation of all the wrapper objects + * occurr in the main thread, because there's less overhead in having + * to allocate temporary storage for their results in a queue so that + * they can be re-dispatched later. The plan is to eventually deprecate + * and remove support for wayland versions <= 1.1. + */ +xwe::IEventQueueStrategy * +EventQueueForClientVersion(IDllWaylandClient &clientLibrary, + struct wl_display *display) +{ + /* TODO: Test for wl_display_read_events / wl_display_prepare_read */ + const bool version12 = + clientLibrary.wl_display_read_events_proc() && + clientLibrary.wl_display_prepare_read_proc(); + if (version12) + return new xw::version_12::EventQueueStrategy(clientLibrary, + display); + else + return new xw::version_11::EventQueueStrategy(clientLibrary, + display); +} +} + +/* Creating a new xbmc::wayland::XBMCConnection effectively creates + * a new xbmc::wayland::Display object, which in turn will connect + * to the running wayland compositor and encapsulate the return value + * from the client library. Then it creates a new + * xbmc::wayland::Registry object which is responsible for managing + * all of the global objects on the wayland connection that we might + * want to use. On creation of this object, a request is sent to + * the compositor to send back an event for every available global + * object. Once we know which objects exist, we can easily + * bind to them. + * + * The WaitForSynchronize call at the end of the constructor is + * important. Once we make a request to the server for all of the + * available global objects, we need to know what they all are + * by the time this constructor finishes running so that the + * object will be complete. The only way to do that is to know + * when our wl_registry.add_listener request has finished processing + * on both the server and client side + */ +xw::XBMCConnection::Private::Private(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + EventInjector &eventInjector) : + m_clientLibrary(clientLibrary), + m_xkbCommonLibrary(xkbCommonLibrary), + m_eventInjector(eventInjector), + m_display(new xw::Display(clientLibrary)), + m_registry(new xw::Registry(clientLibrary, + m_display->GetWlDisplay(), + *this)), + m_compositor(boost::bind(CreateCompositor, _1, &m_clientLibrary), + RequestedCompositorVersion, + clientLibrary.Get_wl_compositor_interface()), + m_shell(boost::bind(CreateShell, _1, &m_clientLibrary), + RequestedShellVersion, + clientLibrary.Get_wl_shell_interface()), + m_seat(RequestedSeatVersion, + clientLibrary.Get_wl_seat_interface(), + boost::bind(&Private::InjectSeat, this)), + m_outputs(boost::bind(CreateOutput, _1, &m_clientLibrary), + RequestedOutputVersion, + clientLibrary.Get_wl_output_interface()), + m_eventQueue(EventQueueForClientVersion(m_clientLibrary, + m_display->GetWlDisplay())) +{ + /* Tell CWinEvents what our event queue is. That way + * CWinEvents::MessagePump is now able to dispatch events from + * the display whenever it is called */ + (*m_eventInjector.setEventQueue)(*(m_eventQueue.get())); + + /* Wait only for the globals to appear, we will wait for + * initialization upon binding them */ + WaitForSynchronize(); +} + +void +xw::XBMCConnection::Private::InjectSeat() +{ + /* When the seat becomes available and bound, let CWinEventsWayland + * know about it so that it can wrap it and query it for more + * information about input devices */ + struct wl_seat *seat = m_seat.FetchPending(*m_registry); + (*m_eventInjector.setWaylandSeat)(m_clientLibrary, + m_xkbCommonLibrary, + seat); +} + +xw::XBMCConnection::Private::~Private() +{ + (*m_eventInjector.destroyWaylandSeat)(); + (*m_eventInjector.destroyEventQueue)(); +} + +xw::XBMCConnection::XBMCConnection(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + EventInjector &eventInjector) : + priv(new Private (clientLibrary, xkbCommonLibrary, eventInjector)) +{ +} + +/* A defined destructor is required such that + * boost::scoped_ptr::~scoped_ptr is generated here */ +xw::XBMCConnection::~XBMCConnection() +{ +} + +xw::Display & +xw::XBMCConnection::Private::Display() +{ + return *m_display; +} + +xw::Compositor & +xw::XBMCConnection::Private::Compositor() +{ + return m_compositor.GetFirst(*m_registry); +} + +xw::Shell & +xw::XBMCConnection::Private::Shell() +{ + return m_shell.GetFirst(*m_registry); +} + +xw::Output & +xw::XBMCConnection::Private::Output() +{ + xw::Output &output(m_outputs.GetFirst(*m_registry)); + + /* Wait for synchronize upon lazy-binding the first output + * and then check if we got any modes */ + WaitForSynchronize(); + if (output.AllModes().empty()) + { + std::stringstream ss; + ss << "No modes detected on first output"; + throw std::runtime_error(ss.str()); + } + return output; +} + +/* Once an object becomes available, we need to take note of that + * fact and store its interface information somewhere. We then + * call a function to indicate to any interested observer that the + * object is available and can be bound to. Callers might not do this + * right away. */ +bool +xw::XBMCConnection::Private::OnGlobalInterfaceAvailable(uint32_t name, + const char *interface, + uint32_t version) +{ + /* A boost::array is effectively immutable so we can leave out + * const here */ + typedef boost::array ConstructorArray; + + + /* Not static, as the pointers here may change in cases where + * Private is re-constructed. + * + * These are sorted into alphabetical order so that we can do + * a simple binary search for them. */ + ConstructorArray constructors = + { + { + { CompositorName.c_str(), &m_compositor }, + { OutputName.c_str(), &m_outputs }, + { SeatName.c_str(), &m_seat }, + { ShellName.c_str(), &m_shell } + } + }; + + /* Simple binary search for a known object constructor that matches + * this interface */ + ConstructorArray::iterator it(std::lower_bound(constructors.begin(), + constructors.end(), + interface, + ConstructorMatchesInterface)); + if (it != constructors.end() && + strcmp(it->interfaceName, interface) == 0) + { + it->interface->OnObjectAvailable(name, version); + return true; + } + + return false; +} + +void xw::XBMCConnection::Private::WaitForSynchronize() +{ + boost::function func(boost::bind(&Private::Synchronize, + this)); + + synchronized = false; + synchronizeCallback.reset(new xw::Callback(m_clientLibrary, + m_display->Sync(), + func)); + + /* For version 1.1 event queues the effect of this is going to be + * a spin-wait. That's not exactly ideal, but we do need to + * continuously flush the event queue */ + while (!synchronized) + (*m_eventInjector.messagePump)(); +} + +void xw::XBMCConnection::Private::Synchronize() +{ + synchronized = true; + synchronizeCallback.reset(); +} + +namespace +{ +void ResolutionInfoForMode(const xw::Output::ModeGeometry &mode, + RESOLUTION_INFO &res) +{ + res.iWidth = mode.width; + res.iHeight = mode.height; + + /* The refresh rate is given as in mHz as integer so we need + * to divide by 1000.0f to get a floating point value in Hz */ + res.fRefreshRate = mode.refresh / 1000.0f; + res.dwFlags = D3DPRESENTFLAG_PROGRESSIVE; + res.iScreen = 0; + res.bFullScreen = true; + res.iSubtitles = static_cast(0.965 * res.iHeight); + res.fPixelRatio = 1.0f; + res.iScreenWidth = res.iWidth; + res.iScreenHeight = res.iHeight; + res.strMode = StringUtils::Format("%dx%d @ %.2fp", + res.iScreenWidth, + res.iScreenHeight, + res.fRefreshRate); +} +} + +void +xw::XBMCConnection::CurrentResolution(RESOLUTION_INFO &res) const +{ + /* Supporting only the first output device at the moment */ + const xw::Output::ModeGeometry ¤t(priv->Output().CurrentMode()); + + ResolutionInfoForMode(current, res); +} + +void +xw::XBMCConnection::PreferredResolution(RESOLUTION_INFO &res) const +{ + /* Supporting only the first output device at the moment */ + const xw::Output::ModeGeometry &preferred(priv->Output().PreferredMode()); + ResolutionInfoForMode(preferred, res); +} + +void +xw::XBMCConnection::AvailableResolutions(std::vector &resolutions) const +{ + /* Supporting only the first output device at the moment */ + xw::Output &output(priv->Output()); + const std::vector &m_modes(output.AllModes()); + + for (std::vector::const_iterator it = m_modes.begin(); + it != m_modes.end(); + ++it) + { + resolutions.push_back(RESOLUTION_INFO()); + RESOLUTION_INFO &back(resolutions.back()); + + ResolutionInfoForMode(*it, back); + } +} + +EGLNativeDisplayType * +xw::XBMCConnection::NativeDisplay() const +{ + return priv->Display().GetEGLNativeDisplay(); +} + +xw::Compositor & +xw::XBMCConnection::GetCompositor() +{ + return priv->Compositor(); +} + +xw::Shell & +xw::XBMCConnection::GetShell() +{ + return priv->Shell(); +} + +xw::Output & +xw::XBMCConnection::GetFirstOutput() +{ + return priv->Output(); +} diff --git a/xbmc/windowing/egl/wayland/XBMCConnection.h b/xbmc/windowing/egl/wayland/XBMCConnection.h new file mode 100644 index 0000000000000..4e1477aa6790d --- /dev/null +++ b/xbmc/windowing/egl/wayland/XBMCConnection.h @@ -0,0 +1,93 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +class IDllWaylandClient; +class IDllXKBCommon; + +struct wl_compositor; +struct wl_display; +struct wl_output; +struct wl_shell; +struct wl_seat; + +typedef struct wl_display * EGLNativeDisplayType; + +struct RESOLUTION_INFO; + +namespace xbmc +{ +namespace wayland +{ +class Compositor; +class Output; +class Shell; + +namespace events +{ +class IEventQueueStrategy; +} + +class XBMCConnection +{ +public: + + struct EventInjector + { + typedef void (*SetEventQueue)(events::IEventQueueStrategy &strategy); + typedef void (*DestroyEventQueue)(); + typedef void (*SetWaylandSeat)(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + struct wl_seat *seat); + typedef void (*DestroyWaylandSeat)(); + typedef bool (*MessagePump)(); + + SetEventQueue setEventQueue; + DestroyEventQueue destroyEventQueue; + SetWaylandSeat setWaylandSeat; + DestroyWaylandSeat destroyWaylandSeat; + MessagePump messagePump; + }; + + XBMCConnection(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + EventInjector &injector); + ~XBMCConnection(); + + void PreferredResolution(RESOLUTION_INFO &res) const; + void CurrentResolution(RESOLUTION_INFO &res) const; + void AvailableResolutions(std::vector &res) const; + + EGLNativeDisplayType * NativeDisplay() const; + + Compositor & GetCompositor(); + Shell & GetShell(); + Output & GetFirstOutput(); + +private: + + class Private; + boost::scoped_ptr priv; +}; +} +} diff --git a/xbmc/windowing/egl/wayland/XBMCSurface.cpp b/xbmc/windowing/egl/wayland/XBMCSurface.cpp new file mode 100644 index 0000000000000..18f565f4900a9 --- /dev/null +++ b/xbmc/windowing/egl/wayland/XBMCSurface.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include +#include +#include +#include + +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/DllWaylandEgl.h" + +#include "Callback.h" +#include "Compositor.h" +#include "OpenGLSurface.h" +#include "Output.h" +#include "Region.h" +#include "Shell.h" +#include "ShellSurface.h" +#include "Surface.h" + +#include "windowing/WaylandProtocol.h" +#include "XBMCSurface.h" + +namespace xbmc +{ +namespace wayland +{ +class XBMCSurface::Private +{ +public: + + Private(IDllWaylandClient &clientLibrary, + IDllWaylandEGL &eglLibrary, + const EventInjector &eventInjector, + Compositor &compositor, + Shell &shell, + uint32_t width, + uint32_t height); + + typedef boost::function RegionFactory; + + IDllWaylandClient &m_clientLibrary; + IDllWaylandEGL &m_eglLibrary; + + EventInjector m_eventInjector; + + /* We only care about xbmc::Compositor's CreateRegion function + * and don't want to store a pointer to the compositor to create + * a region later */ + RegionFactory m_regionFactory; + + boost::scoped_ptr m_surface; + boost::scoped_ptr m_shellSurface; + boost::scoped_ptr m_glSurface; + boost::scoped_ptr m_frameCallback; + + void OnFrameCallback(uint32_t); + void AddFrameCallback(); +}; +} +} + +namespace xw = xbmc::wayland; + +/* Creating a new xbmc::wayland::XBMCSurface effectively creates + * an OpenGL ES bindable EGL Window and a corresponding + * surface object for the compositor to display it on-screen. It also + * creates a "shell surface", which is a special extension to a normal + * surface which adds window-management functionality to a surface. + * + * If there are any errors in creating the surface they will be thrown + * as std::runtime_errors and the object that creates this one + * needs to handle catching them. + */ +xw::XBMCSurface::Private::Private(IDllWaylandClient &clientLibrary, + IDllWaylandEGL &eglLibrary, + const EventInjector &eventInjector, + Compositor &compositor, + Shell &shell, + uint32_t width, + uint32_t height) : + m_clientLibrary(clientLibrary), + m_eglLibrary(eglLibrary), + m_eventInjector(eventInjector), + m_regionFactory(boost::bind(&Compositor::CreateRegion, + &compositor)), + m_surface(new xw::Surface(m_clientLibrary, + compositor.CreateSurface())), + m_shellSurface(new xw::ShellSurface(m_clientLibrary, + shell.CreateShellSurface( + m_surface->GetWlSurface()))), + /* Creating a new xbmc::wayland::OpenGLSurface will manage the + * attach-and-commit process on eglSwapBuffers */ + m_glSurface(new xw::OpenGLSurface(m_eglLibrary, + m_surface->GetWlSurface(), + width, + height)) +{ + /* SetOpaqueRegion here is an important optimization for the + * compositor. It effectively tells it that this window is completely + * opaque. This means that the window can be rendered without + * the use of GL_BLEND which represents a substantial rendering + * speedup, especially for larger surfaces. It also means that + * this window can be placed in an overlay plane, so it can + * skip compositing alltogether */ + xw::Region region(m_clientLibrary, m_regionFactory()); + + region.AddRectangle(0, 0, 640, 480); + + m_surface->SetOpaqueRegion(region.GetWlRegion()); + m_surface->Commit(); + + /* The compositor is responsible for letting us know when to + * draw things. This is effectively to conserve battery life + * where drawing our surface would be a futile operation. Its not + * entirely applicable to the xbmc case because we use a game loop, + * but some compositor expect it, so we must add a frame callback + * as soon as the surface is ready to be rendered to */ + AddFrameCallback(); + + (*m_eventInjector.setXBMCSurface)(m_surface->GetWlSurface()); +} + +xw::XBMCSurface::XBMCSurface(IDllWaylandClient &clientLibrary, + IDllWaylandEGL &eglLibrary, + const EventInjector &eventInjector, + Compositor &compositor, + Shell &shell, + uint32_t width, + uint32_t height) : + priv(new Private(clientLibrary, + eglLibrary, + eventInjector, + compositor, + shell, + width, + height)) +{ +} + +/* A defined destructor is required such that + * boost::scoped_ptr::~scoped_ptr is generated here */ +xw::XBMCSurface::~XBMCSurface() +{ +} + +void +xw::XBMCSurface::Show(xw::Output &output) +{ + /* Calling SetFullscreen will implicitly show the surface, center + * it as full-screen on the selected output and change the resolution + * of the output so as to fit as much of the surface as possible + * without adding black bars. + * + * While the surface is fullscreen, any attempt to resize it will + * result in the resolution changing to the nearest match */ + priv->m_shellSurface->SetFullscreen(WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER, + 0, + output.GetWlOutput()); +} + +void +xw::XBMCSurface::Resize(uint32_t width, uint32_t height) +{ + /* Since the xbmc::wayland::OpenGLSurface owns the buffer, it is + * responsible for changing its size. When the size changes, the + * opaque region must also change */ + priv->m_glSurface->Resize(width, height); + + xw::Region region(priv->m_clientLibrary, + priv->m_regionFactory()); + + region.AddRectangle(0, 0, width, height); + + priv->m_surface->SetOpaqueRegion(region.GetWlRegion()); + priv->m_surface->Commit(); +} + +EGLNativeWindowType * +xw::XBMCSurface::EGLNativeWindow() const +{ + return priv->m_glSurface->GetEGLNativeWindow(); +} + +void xw::XBMCSurface::Private::OnFrameCallback(uint32_t time) +{ + AddFrameCallback(); +} + +void xw::XBMCSurface::Private::AddFrameCallback() +{ + m_frameCallback.reset(new xw::Callback(m_clientLibrary, + m_surface->CreateFrameCallback(), + boost::bind(&Private::OnFrameCallback, + this, + _1))); +} diff --git a/xbmc/windowing/egl/wayland/XBMCSurface.h b/xbmc/windowing/egl/wayland/XBMCSurface.h new file mode 100644 index 0000000000000..c7d6531035c92 --- /dev/null +++ b/xbmc/windowing/egl/wayland/XBMCSurface.h @@ -0,0 +1,74 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +class IDllWaylandClient; +class IDllWaylandEGL; + +struct wl_region; + +typedef struct wl_egl_window * EGLNativeWindowType; + +namespace xbmc +{ +namespace wayland +{ +class Callback; +class Compositor; +class OpenGLSurface; +class Output; +class Shell; +class ShellSurface; +class Surface; + +class XBMCSurface +{ +public: + + struct EventInjector + { + typedef void (*SetXBMCSurface)(struct wl_surface *); + + SetXBMCSurface setXBMCSurface; + }; + + XBMCSurface(IDllWaylandClient &clientLibrary, + IDllWaylandEGL &eglLibrary, + const EventInjector &eventInjector, + Compositor &compositor, + Shell &shell, + uint32_t width, + uint32_t height); + ~XBMCSurface(); + + void Show(Output &output); + void Resize(uint32_t width, uint32_t height); + EGLNativeWindowType * EGLNativeWindow() const; + +private: + + class Private; + boost::scoped_ptr priv; +}; +} +} diff --git a/xbmc/windowing/tests/wayland/Makefile.in b/xbmc/windowing/tests/wayland/Makefile.in new file mode 100644 index 0000000000000..5c1690b02666e --- /dev/null +++ b/xbmc/windowing/tests/wayland/Makefile.in @@ -0,0 +1,51 @@ +ifeq (@USE_WAYLAND@,1) +SRCS = StubCursorManager.cpp \ + StubEventListener.cpp \ + TestEGLNativeTypeWayland.cpp \ + TestWaylandInputUnit.cpp \ + TestXBMCWaylandInputAcceptance.cpp \ + TmpEnv.cpp \ + WestonProcess.cpp \ + WestonTest.cpp \ + XBMCWayland.cpp + +WAYLAND_TEST_MODULE_PROTOCOL = protocol.xml +WAYLAND_TEST_MODULE_PROTOCOL_SRCS = xbmc_wayland_test_protocol.c +WAYLAND_TEST_MODULE_PROTOCOL_GENERATED_SRCS = $(WAYLAND_TEST_MODULE_PROTOCOL_SRCS) +WAYLAND_TEST_MODULE_PROTOCOL_GENERATED_SRCS += xbmc_wayland_test_server_protocol.h +WAYLAND_TEST_MODULE_PROTOCOL_GENERATED_SRCS += xbmc_wayland_test_client_protocol.h +WAYLAND_TEST_MODULE_SRCS = XBMCWaylandTestExtension.cpp + +INCLUDES += -I@abs_top_srcdir@/lib/gtest/include -I@WAYLAND_TEST_INCLUDES@ +LIB = test_wayland.a + +ifneq (,@WAYLAND_SCANNER@) +SRCS += $(WAYLAND_TEST_MODULE_PROTOCOL_SRCS) +endif + +CLEAN_FILES += $(WAYLAND_TEST_MODULE_PROTOCOL_GENERATED_SRCS) xbmc-wayland-test-extension.so + +include @abs_top_srcdir@/Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(patsubst %.h,%.P,$(SRCS)))) + +ifneq (,@WAYLAND_SCANNER@) +TestEGLNativeTypeWayland.cpp : xbmc_wayland_test_client_protocol.h + +$(WAYLAND_TEST_MODULE_SRCS) : $(WAYLAND_TEST_MODULE_PROTOCOL_GENERATED_SRCS) + +xbmc_wayland_test_protocol.c: $(WAYLAND_TEST_MODULE_PROTOCOL) + @WAYLAND_SCANNER@ code < $< > $@ + +xbmc_wayland_test_server_protocol.h: $(WAYLAND_TEST_MODULE_PROTOCOL) + @WAYLAND_SCANNER@ server-header < $< > $@ + +xbmc_wayland_test_client_protocol.h: $(WAYLAND_TEST_MODULE_PROTOCOL) + @WAYLAND_SCANNER@ client-header < $< > $@ + +ifeq (@USE_WAYLAND_TEST_EXTENSION@,1) +xbmc-wayland-test-extension.so: $(WAYLAND_TEST_MODULE_PROTOCOL_SRCS:.c=.o) $(WAYLAND_TEST_MODULE_SRCS:.cpp=.o) + $(SILENT_LD) $(CXX) $(CXXFLAGS) $(LDFLAGS) $(WAYLAND_TEST_LIBS) -shared -o $@ $+ -rdynamic +endif + +endif +endif diff --git a/xbmc/windowing/tests/wayland/StubCursorManager.cpp b/xbmc/windowing/tests/wayland/StubCursorManager.cpp new file mode 100644 index 0000000000000..c3fc77464527c --- /dev/null +++ b/xbmc/windowing/tests/wayland/StubCursorManager.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "StubCursorManager.h" + +void +StubCursorManager::SetCursor(uint32_t serial, + struct wl_surface *surface, + double surfaceX, + double surfaceY) +{ +} diff --git a/xbmc/windowing/tests/wayland/StubCursorManager.h b/xbmc/windowing/tests/wayland/StubCursorManager.h new file mode 100644 index 0000000000000..05273cb7ca34d --- /dev/null +++ b/xbmc/windowing/tests/wayland/StubCursorManager.h @@ -0,0 +1,35 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +struct wl_surface; + +class StubCursorManager : + public xbmc::ICursorManager +{ +public: + + void SetCursor(uint32_t serial, + struct wl_surface *surface, + double surfaceX, + double surfaceY); +}; diff --git a/xbmc/windowing/tests/wayland/StubEventListener.cpp b/xbmc/windowing/tests/wayland/StubEventListener.cpp new file mode 100644 index 0000000000000..b091843ba66ea --- /dev/null +++ b/xbmc/windowing/tests/wayland/StubEventListener.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "StubEventListener.h" + +StubEventListener::StubEventListener() : + m_focused(false) +{ +} + +XBMC_Event +StubEventListener::FetchLastEvent() +{ + if (m_events.empty()) + throw std::logic_error("No events left to get!"); + + XBMC_Event ev = m_events.front(); + m_events.pop(); + return ev; +} + +bool +StubEventListener::Focused() +{ + return m_focused; +} + +void +StubEventListener::OnFocused() +{ + m_focused = true; +} + +void +StubEventListener::OnUnfocused() +{ + m_focused = false; +} + +void +StubEventListener::OnEvent(XBMC_Event &ev) +{ + m_events.push(ev); +} diff --git a/xbmc/windowing/tests/wayland/StubEventListener.h b/xbmc/windowing/tests/wayland/StubEventListener.h new file mode 100644 index 0000000000000..5a15305a54696 --- /dev/null +++ b/xbmc/windowing/tests/wayland/StubEventListener.h @@ -0,0 +1,45 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "windowing/wayland/EventListener.h" + +class StubEventListener : + public xbmc::IEventListener +{ +public: + + StubEventListener(); + + /* Returns front of event queue, otherwise throws */ + XBMC_Event FetchLastEvent(); + bool Focused(); + +private: + + void OnFocused(); + void OnUnfocused(); + void OnEvent(XBMC_Event &); + + bool m_focused; + std::queue m_events; +}; diff --git a/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp b/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp new file mode 100644 index 0000000000000..84a904e4efc3b --- /dev/null +++ b/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "system.h" + +#define WL_EGL_PLATFORM + +#include +#include + +#include + +#include + +#include +#include + +#if defined(HAVE_WAYLAND_XBMC_PROTO) +#include "xbmc_wayland_test_client_protocol.h" +#endif + +#include "windowing/egl/wayland/Display.h" +#include "windowing/egl/wayland/Registry.h" +#include "windowing/egl/wayland/Surface.h" +#include "windowing/egl/EGLNativeTypeWayland.h" + +#include "TmpEnv.h" +#include "WestonTest.h" +#include "XBMCWayland.h" + +using ::testing::Values; +using ::testing::WithParamInterface; + +namespace xt = xbmc::test; +namespace xw = xbmc::wayland; +namespace xtw = xbmc::test::wayland; + +class EGLNativeTypeWaylandWestonTest : + public WestonTest +{ +protected: + + CEGLNativeTypeWayland m_nativeType; +}; + +TEST_F(EGLNativeTypeWaylandWestonTest, TestCheckCompatibilityWithEnvSet) +{ + TmpEnv env("WAYLAND_DISPLAY", TempSocketName().c_str()); + EXPECT_TRUE(m_nativeType.CheckCompatibility()); +} + +TEST_F(EGLNativeTypeWaylandWestonTest, TestCheckCompatibilityWithEnvNotSet) +{ + EXPECT_FALSE(m_nativeType.CheckCompatibility()); +} + +class CompatibleEGLNativeTypeWaylandWestonTest : + public EGLNativeTypeWaylandWestonTest +{ +public: + + CompatibleEGLNativeTypeWaylandWestonTest(); + virtual void SetUp(); + +private: + + TmpEnv m_waylandDisplayEnv; +}; + +CompatibleEGLNativeTypeWaylandWestonTest::CompatibleEGLNativeTypeWaylandWestonTest() : + m_waylandDisplayEnv("WAYLAND_DISPLAY", + TempSocketName().c_str()) +{ +} + +void +CompatibleEGLNativeTypeWaylandWestonTest::SetUp() +{ + WestonTest::SetUp(); + ASSERT_TRUE(m_nativeType.CheckCompatibility()); +} + +TEST_F(CompatibleEGLNativeTypeWaylandWestonTest, TestConnection) +{ + EXPECT_TRUE(m_nativeType.CreateNativeDisplay()); +} + +class ConnectedEGLNativeTypeWaylandWestonTest : + public CompatibleEGLNativeTypeWaylandWestonTest +{ +public: + + ConnectedEGLNativeTypeWaylandWestonTest(); + ~ConnectedEGLNativeTypeWaylandWestonTest(); + virtual void SetUp(); + +protected: + + xw::Display *m_display; + struct wl_surface *m_mostRecentSurface; + +private: + + void Global(struct wl_registry *, uint32_t, const char *, uint32_t); + void DisplayAvailable(xw::Display &display); + void SurfaceCreated(xw::Surface &surface); +}; + +ConnectedEGLNativeTypeWaylandWestonTest::ConnectedEGLNativeTypeWaylandWestonTest() +{ + xw::WaylandDisplayListener &displayListener(xw::WaylandDisplayListener::GetInstance()); + displayListener.SetHandler(boost::bind(&ConnectedEGLNativeTypeWaylandWestonTest::DisplayAvailable, + this, _1)); + + xw::WaylandSurfaceListener &surfaceListener(xw::WaylandSurfaceListener::GetInstance()); + surfaceListener.SetHandler(boost::bind(&ConnectedEGLNativeTypeWaylandWestonTest::SurfaceCreated, + this, _1)); +} + +ConnectedEGLNativeTypeWaylandWestonTest::~ConnectedEGLNativeTypeWaylandWestonTest() +{ + xw::WaylandDisplayListener &displayListener(xw::WaylandDisplayListener::GetInstance()); + displayListener.SetHandler(xw::WaylandDisplayListener::Handler()); + + xw::WaylandSurfaceListener &surfaceListener(xw::WaylandSurfaceListener::GetInstance()); + surfaceListener.SetHandler(xw::WaylandSurfaceListener::Handler()); +} + +void +ConnectedEGLNativeTypeWaylandWestonTest::SetUp() +{ + CompatibleEGLNativeTypeWaylandWestonTest::SetUp(); + ASSERT_TRUE(m_nativeType.CreateNativeDisplay()); +} + +void +ConnectedEGLNativeTypeWaylandWestonTest::DisplayAvailable(xw::Display &display) +{ + m_display = &display; +} + +void +ConnectedEGLNativeTypeWaylandWestonTest::SurfaceCreated(xw::Surface &surface) +{ + m_mostRecentSurface = surface.GetWlSurface(); +} + +TEST_F(ConnectedEGLNativeTypeWaylandWestonTest, CreateNativeWindowSuccess) +{ + EXPECT_TRUE(m_nativeType.CreateNativeWindow()); +} + +TEST_F(ConnectedEGLNativeTypeWaylandWestonTest, ProbeResolutionsSuccess) +{ + std::vector info; + EXPECT_TRUE(m_nativeType.ProbeResolutions(info)); +} + +TEST_F(ConnectedEGLNativeTypeWaylandWestonTest, PreferredResolutionSuccess) +{ + RESOLUTION_INFO info; + EXPECT_TRUE(m_nativeType.GetPreferredResolution(&info)); +} + +TEST_F(ConnectedEGLNativeTypeWaylandWestonTest, CurrentNativeSuccess) +{ + RESOLUTION_INFO info; + EXPECT_TRUE(m_nativeType.GetNativeResolution(&info)); +} + +TEST_F(ConnectedEGLNativeTypeWaylandWestonTest, GetMostRecentSurface) +{ + m_nativeType.CreateNativeWindow(); + EXPECT_TRUE(m_mostRecentSurface != NULL); +} + +#if defined(HAVE_WAYLAND_XBMC_PROTO) + +class AssistedEGLNativeTypeWaylandTest : + public ConnectedEGLNativeTypeWaylandWestonTest +{ +protected: + + AssistedEGLNativeTypeWaylandTest(); + ~AssistedEGLNativeTypeWaylandTest(); + + virtual void SetUp(); + + void Global(struct wl_registry *registry, + uint32_t name, + const char *interface, + uint32_t version); + + boost::scoped_ptr m_xbmcWayland; +}; + +AssistedEGLNativeTypeWaylandTest::AssistedEGLNativeTypeWaylandTest() +{ + xw::ExtraWaylandGlobals &extra(xw::ExtraWaylandGlobals::GetInstance()); + extra.SetHandler(boost::bind(&AssistedEGLNativeTypeWaylandTest::Global, + this, _1, _2, _3, _4)); +} + +AssistedEGLNativeTypeWaylandTest::~AssistedEGLNativeTypeWaylandTest() +{ + xw::ExtraWaylandGlobals &extra(xw::ExtraWaylandGlobals::GetInstance()); + extra.SetHandler(xw::ExtraWaylandGlobals::GlobalHandler()); +} + +void +AssistedEGLNativeTypeWaylandTest::SetUp() +{ + ConnectedEGLNativeTypeWaylandWestonTest::SetUp(); + ASSERT_TRUE(m_xbmcWayland.get()); +} + +void +AssistedEGLNativeTypeWaylandTest::Global(struct wl_registry *registry, + uint32_t name, + const char *interface, + uint32_t version) +{ + if (std::string(interface) == "xbmc_wayland") + m_xbmcWayland.reset(new xtw::XBMCWayland(static_cast(wl_registry_bind(registry, + name, + &xbmc_wayland_interface, + version)))); +} + +TEST_F(AssistedEGLNativeTypeWaylandTest, TestGotXBMCWayland) +{ + EXPECT_TRUE(m_xbmcWayland.get() != NULL); +} + +TEST_F(AssistedEGLNativeTypeWaylandTest, AdditionalResolutions) +{ + m_xbmcWayland->AddMode(2, 2, 2, static_cast(0)); + std::vector resolutions; + m_nativeType.ProbeResolutions(resolutions); + EXPECT_TRUE(resolutions.size() == 2); +} + +TEST_F(AssistedEGLNativeTypeWaylandTest, PreferredResolutionChange) +{ + m_xbmcWayland->AddMode(2, 2, 2, static_cast(WL_OUTPUT_MODE_PREFERRED)); + RESOLUTION_INFO res; + m_nativeType.GetPreferredResolution(&res); + EXPECT_EQ(res.iWidth, 2); + EXPECT_EQ(res.iHeight, 2); +} + +TEST_F(AssistedEGLNativeTypeWaylandTest, CurrentResolutionChange) +{ + m_xbmcWayland->AddMode(2, 2, 2, static_cast(WL_OUTPUT_MODE_CURRENT)); + RESOLUTION_INFO res; + m_nativeType.GetNativeResolution(&res); + EXPECT_EQ(res.iWidth, 2); + EXPECT_EQ(res.iHeight, 2); +} + +#endif diff --git a/xbmc/windowing/tests/wayland/TestWaylandInputUnit.cpp b/xbmc/windowing/tests/wayland/TestWaylandInputUnit.cpp new file mode 100644 index 0000000000000..3ea559b2dfeb9 --- /dev/null +++ b/xbmc/windowing/tests/wayland/TestWaylandInputUnit.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +#include + +#include "windowing/wayland/Pointer.h" +#include "windowing/wayland/PointerProcessor.h" + +#include "StubCursorManager.h" +#include "StubEventListener.h" + +using ::testing::Values; +using ::testing::WithParamInterface; + +namespace xw = xbmc::wayland; + +class WaylandPointerProcessor : + public ::testing::Test +{ +public: + + WaylandPointerProcessor(); + +protected: + + StubCursorManager cursorManager; + StubEventListener listener; + xbmc::PointerProcessor processor; +}; + +WaylandPointerProcessor::WaylandPointerProcessor() : + processor(listener, cursorManager) +{ +} + +class WaylandPointerProcessorButtons : + public WaylandPointerProcessor, + public WithParamInterface > +{ +protected: + + uint32_t WaylandButton(); + uint32_t XBMCButton(); +}; + +uint32_t WaylandPointerProcessorButtons::WaylandButton() +{ + return std::tr1::get<0>(GetParam()); +} + +uint32_t WaylandPointerProcessorButtons::XBMCButton() +{ + return std::tr1::get<1>(GetParam()); +} + +TEST_P(WaylandPointerProcessorButtons, ButtonPress) +{ + xw::IPointerReceiver &receiver = + static_cast(processor); + receiver.Button(0, 0, WaylandButton(), WL_POINTER_BUTTON_STATE_PRESSED); + + XBMC_Event event(listener.FetchLastEvent()); + EXPECT_EQ(XBMC_MOUSEBUTTONDOWN, event.type); + EXPECT_EQ(XBMCButton(), event.button.button); +} + +TEST_P(WaylandPointerProcessorButtons, ButtonRelease) +{ + xw::IPointerReceiver &receiver = + static_cast(processor); + receiver.Button(0, 0, WaylandButton(), WL_POINTER_BUTTON_STATE_RELEASED); + + XBMC_Event event(listener.FetchLastEvent()); + EXPECT_EQ(XBMC_MOUSEBUTTONUP, event.type); + EXPECT_EQ(XBMCButton(), event.button.button); +} + +INSTANTIATE_TEST_CASE_P(ThreeButtonMouse, + WaylandPointerProcessorButtons, + Values(std::tr1::tuple(272, 1), + std::tr1::tuple(274, 2), + std::tr1::tuple(273, 3))); + +class WaylandPointerProcessorAxisButtons : + public WaylandPointerProcessor, + public WithParamInterface > +{ +protected: + + float Magnitude(); + uint32_t XBMCButton(); +}; + +float WaylandPointerProcessorAxisButtons::Magnitude() +{ + return std::tr1::get<0>(GetParam()); +} + +uint32_t WaylandPointerProcessorAxisButtons::XBMCButton() +{ + return std::tr1::get<1>(GetParam()); +} + +TEST_P(WaylandPointerProcessorAxisButtons, Axis) +{ + xw::IPointerReceiver &receiver = + static_cast(processor); + receiver.Axis(0, WL_POINTER_AXIS_VERTICAL_SCROLL, Magnitude()); + + XBMC_Event event(listener.FetchLastEvent()); + EXPECT_EQ(XBMC_MOUSEBUTTONDOWN, event.type); + EXPECT_EQ(XBMCButton(), event.button.button); + + event = listener.FetchLastEvent(); + EXPECT_EQ(XBMC_MOUSEBUTTONUP, event.type); + EXPECT_EQ(XBMCButton(), event.button.button); +} + +INSTANTIATE_TEST_CASE_P(VerticalScrollWheel, + WaylandPointerProcessorAxisButtons, + Values(std::tr1::tuple(-1.0, 4), + std::tr1::tuple(1.0, 5))); + +TEST_F(WaylandPointerProcessor, Motion) +{ + const float x = 5.0; + const float y = 5.0; + xw::IPointerReceiver &receiver = + static_cast(processor); + receiver.Motion(0, x, y); + + XBMC_Event event(listener.FetchLastEvent()); + EXPECT_EQ(XBMC_MOUSEMOTION, event.type); + EXPECT_EQ(::round(x), event.motion.xrel); + EXPECT_EQ(::round(y), event.motion.yrel); +} + +TEST_F(WaylandPointerProcessor, MotionThenButton) +{ + const float x = 5.0; + const float y = 5.0; + xw::IPointerReceiver &receiver = + static_cast(processor); + receiver.Motion(0, x, y); + receiver.Button(0, 0, 272, WL_POINTER_BUTTON_STATE_PRESSED); + + listener.FetchLastEvent(); + XBMC_Event event(listener.FetchLastEvent()); + EXPECT_EQ(XBMC_MOUSEBUTTONDOWN, event.type); + EXPECT_EQ(::round(x), event.button.y); + EXPECT_EQ(::round(y), event.button.x); +} diff --git a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp new file mode 100644 index 0000000000000..4f66ead2ada48 --- /dev/null +++ b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp @@ -0,0 +1,581 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#define WL_EGL_PLATFORM + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include "xbmc_wayland_test_client_protocol.h" +#include "windowing/DllWaylandClient.h" +#include "windowing/DllWaylandEgl.h" +#include "windowing/DllXKBCommon.h" + +#include "windowing/egl/wayland/Callback.h" +#include "windowing/egl/wayland/Compositor.h" +#include "windowing/egl/wayland/Display.h" +#include "windowing/egl/wayland/OpenGLSurface.h" +#include "windowing/egl/wayland/Registry.h" +#include "windowing/egl/wayland/Surface.h" +#include "windowing/egl/wayland/Shell.h" +#include "windowing/egl/wayland/ShellSurface.h" +#include "windowing/egl/EGLNativeTypeWayland.h" +#include "windowing/wayland/EventLoop.h" +#include "windowing/wayland/EventQueueStrategy.h" +#include "windowing/wayland/TimeoutManager.h" +#include "windowing/wayland/CursorManager.h" +#include "windowing/wayland/InputFactory.h" +#include "windowing/wayland/Wayland11EventQueueStrategy.h" +#include "windowing/wayland/Wayland12EventQueueStrategy.h" + +#include "input/linux/XKBCommonKeymap.h" +#include "input/XBMC_keysym.h" + +#include "StubCursorManager.h" +#include "StubEventListener.h" +#include "TmpEnv.h" +#include "WestonTest.h" +#include "XBMCWayland.h" + +#define WAYLAND_VERSION_NUMBER ((WAYLAND_VERSION_MAJOR << 16) | (WAYLAND_VERSION_MINOR << 8) | (WAYLAND_VERSION_MICRO)) +#define WAYLAND_VERSION_CHECK(major, minor, micro) ((major << 16) | (minor << 8) | (micro)) + +namespace xw = xbmc::wayland; +namespace xtw = xbmc::test::wayland; +namespace xwe = xbmc::wayland::events; + +namespace +{ +class SingleThreadedEventQueue : + public xwe::IEventQueueStrategy +{ +public: + + SingleThreadedEventQueue(IDllWaylandClient &clientLibrary, + struct wl_display *display); + +private: + + void PushAction(const Action &action); + void DispatchEventsFromMain(); + + IDllWaylandClient &m_clientLibrary; + struct wl_display *m_display; +}; + +SingleThreadedEventQueue::SingleThreadedEventQueue(IDllWaylandClient &clientLibrary, + struct wl_display *display) : + m_clientLibrary(clientLibrary), + m_display(display) +{ +} + +void SingleThreadedEventQueue::PushAction(const Action &action) +{ + action(); +} + +void SingleThreadedEventQueue::DispatchEventsFromMain() +{ + m_clientLibrary.wl_display_dispatch_pending(m_display); + m_clientLibrary.wl_display_flush(m_display); + m_clientLibrary.wl_display_dispatch(m_display); +} +} + +class InputEventsWestonTest : + public WestonTest, + public xw::IWaylandRegistration +{ +public: + + InputEventsWestonTest(); + virtual void SetUp(); + +protected: + + DllWaylandClient clientLibrary; + DllWaylandEGL eglLibrary; + DllXKBCommon xkbCommonLibrary; + + StubCursorManager cursors; + StubEventListener listener; + + boost::shared_ptr xkbContext; + boost::scoped_ptr keymap; + + boost::scoped_ptr display; + boost::scoped_ptr queue; + boost::scoped_ptr registry; + + boost::scoped_ptr loop; + boost::scoped_ptr input; + + boost::scoped_ptr compositor; + boost::scoped_ptr shell; + boost::scoped_ptr xbmcWayland; + + boost::scoped_ptr surface; + boost::scoped_ptr shellSurface; + boost::scoped_ptr openGLSurface; + + virtual xwe::IEventQueueStrategy * CreateEventQueue() = 0; + + void WaitForSynchronize(); + + static const unsigned int SurfaceWidth = 512; + static const unsigned int SurfaceHeight = 512; + +private: + + virtual bool OnGlobalInterfaceAvailable(uint32_t name, + const char *interface, + uint32_t version); + + bool synchronized; + void Synchronize(); + boost::scoped_ptr syncCallback; + + TmpEnv m_waylandDisplayEnv; +}; + +InputEventsWestonTest::InputEventsWestonTest() : + m_waylandDisplayEnv("WAYLAND_DISPLAY", + TempSocketName().c_str()) +{ +} + +void InputEventsWestonTest::SetUp() +{ + WestonTest::SetUp(); + + clientLibrary.Load(); + eglLibrary.Load(); + xkbCommonLibrary.Load(); + + xkbContext.reset(CXKBKeymap::CreateXKBContext(xkbCommonLibrary), + boost::bind(&IDllXKBCommon::xkb_context_unref, + &xkbCommonLibrary, _1)); + keymap.reset(new CXKBKeymap( + xkbCommonLibrary, + CXKBKeymap::CreateXKBKeymapFromNames(xkbCommonLibrary, + xkbContext.get(), + "evdev", + "pc105", + "us", + "", + ""))); + + display.reset(new xw::Display(clientLibrary)); + queue.reset(CreateEventQueue()); + registry.reset(new xw::Registry(clientLibrary, + display->GetWlDisplay(), + *this)); + loop.reset(new xwe::Loop(listener, *queue)); + + /* Wait for the seat, shell, compositor to appear */ + WaitForSynchronize(); + + ASSERT_TRUE(input.get() != NULL); + ASSERT_TRUE(compositor.get() != NULL); + ASSERT_TRUE(shell.get() != NULL); + ASSERT_TRUE(xbmcWayland.get() != NULL); + + /* Wait for input devices to appear etc */ + WaitForSynchronize(); + + surface.reset(new xw::Surface(clientLibrary, + compositor->CreateSurface())); + shellSurface.reset(new xw::ShellSurface(clientLibrary, + shell->CreateShellSurface( + surface->GetWlSurface()))); + openGLSurface.reset(new xw::OpenGLSurface(eglLibrary, + surface->GetWlSurface(), + SurfaceWidth, + SurfaceHeight)); + + wl_shell_surface_set_toplevel(shellSurface->GetWlShellSurface()); + surface->Commit(); +} + +bool InputEventsWestonTest::OnGlobalInterfaceAvailable(uint32_t name, + const char *interface, + uint32_t version) +{ + if (strcmp(interface, "wl_seat") == 0) + { + /* We must use the one provided by dlopen, as the address + * may be different */ + struct wl_interface **seatInterface = + clientLibrary.Get_wl_seat_interface(); + struct wl_seat *seat = + registry->Bind(name, + seatInterface, + 1); + input.reset(new xbmc::InputFactory(clientLibrary, + xkbCommonLibrary, + seat, + listener, + *loop)); + return true; + } + else if (strcmp(interface, "wl_compositor") == 0) + { + struct wl_interface **compositorInterface = + clientLibrary.Get_wl_compositor_interface(); + struct wl_compositor *wlcompositor = + registry->Bind(name, + compositorInterface, + 1); + compositor.reset(new xw::Compositor(clientLibrary, wlcompositor)); + return true; + } + else if (strcmp(interface, "wl_shell") == 0) + { + struct wl_interface **shellInterface = + clientLibrary.Get_wl_shell_interface(); + struct wl_shell *wlshell = + registry->Bind(name, + shellInterface, + 1); + shell.reset(new xw::Shell(clientLibrary, wlshell)); + return true; + } + else if (strcmp(interface, "xbmc_wayland") == 0) + { + struct wl_interface **xbmcWaylandInterface = + (struct wl_interface **) &xbmc_wayland_interface; + struct xbmc_wayland *wlxbmc_wayland = + registry->Bind(name, + xbmcWaylandInterface, + version); + xbmcWayland.reset(new xtw::XBMCWayland(wlxbmc_wayland)); + return true; + } + + return false; +} + +void InputEventsWestonTest::WaitForSynchronize() +{ + synchronized = false; + syncCallback.reset(new xw::Callback(clientLibrary, + display->Sync(), + boost::bind(&InputEventsWestonTest::Synchronize, + this))); + + while (!synchronized) + loop->Dispatch(); +} + +void InputEventsWestonTest::Synchronize() +{ + synchronized = true; +} + +template +class InputEventQueueWestonTest : + public InputEventsWestonTest +{ +private: + + virtual xwe::IEventQueueStrategy * CreateEventQueue() + { + return new EventQueue(clientLibrary, display->GetWlDisplay()); + } +}; +TYPED_TEST_CASE_P(InputEventQueueWestonTest); + +TYPED_TEST_P(InputEventQueueWestonTest, Construction) +{ +} + +TYPED_TEST_P(InputEventQueueWestonTest, MotionEvent) +{ + typedef InputEventsWestonTest Base; + int x = Base::SurfaceWidth / 2; + int y = Base::SurfaceHeight / 2; + Base::xbmcWayland->MovePointerTo(Base::surface->GetWlSurface(), + wl_fixed_from_int(x), + wl_fixed_from_int(y)); + Base::WaitForSynchronize(); + XBMC_Event event(Base::listener.FetchLastEvent()); + + EXPECT_EQ(XBMC_MOUSEMOTION, event.type); + EXPECT_EQ(x, event.motion.xrel); + EXPECT_EQ(y, event.motion.yrel); +} + +TYPED_TEST_P(InputEventQueueWestonTest, ButtonEvent) +{ + typedef InputEventsWestonTest Base; + int x = Base::SurfaceWidth / 2; + int y = Base::SurfaceHeight / 2; + const unsigned int WaylandLeftButton = 272; + + Base::xbmcWayland->MovePointerTo(Base::surface->GetWlSurface(), + wl_fixed_from_int(x), + wl_fixed_from_int(y)); + Base::xbmcWayland->SendButtonTo(Base::surface->GetWlSurface(), + WaylandLeftButton, + WL_POINTER_BUTTON_STATE_PRESSED); + Base::WaitForSynchronize(); + + /* Throw away motion event */ + Base::listener.FetchLastEvent(); + + XBMC_Event event(Base::listener.FetchLastEvent()); + + EXPECT_EQ(XBMC_MOUSEBUTTONDOWN, event.type); + EXPECT_EQ(1, event.button.button); + EXPECT_EQ(x, event.button.x); + EXPECT_EQ(y, event.button.y); +} + +TYPED_TEST_P(InputEventQueueWestonTest, AxisEvent) +{ + typedef InputEventsWestonTest Base; + int x = Base::SurfaceWidth / 2; + int y = Base::SurfaceHeight / 2; + + Base::xbmcWayland->MovePointerTo(Base::surface->GetWlSurface(), + wl_fixed_from_int(x), + wl_fixed_from_int(y)); + Base::xbmcWayland->SendAxisTo(Base::surface->GetWlSurface(), + WL_POINTER_AXIS_VERTICAL_SCROLL, + wl_fixed_from_int(10)); + Base::WaitForSynchronize(); + + /* Throw away motion event */ + Base::listener.FetchLastEvent(); + + /* Should get button up and down */ + XBMC_Event event(Base::listener.FetchLastEvent()); + + EXPECT_EQ(XBMC_MOUSEBUTTONDOWN, event.type); + EXPECT_EQ(5, event.button.button); + EXPECT_EQ(x, event.button.x); + EXPECT_EQ(y, event.button.y); + + event = Base::listener.FetchLastEvent(); + + EXPECT_EQ(XBMC_MOUSEBUTTONUP, event.type); + EXPECT_EQ(5, event.button.button); + EXPECT_EQ(x, event.button.x); + EXPECT_EQ(y, event.button.y); +} + +namespace +{ +/* Brute-force lookup functions to compensate for the fact that + * Keymap interface only supports conversion from scancodes + * to keysyms and not vice-versa (as such is not implemented in + * xkbcommon) + */ +uint32_t LookupKeycodeForKeysym(ILinuxKeymap &keymap, + XBMCKey sym) +{ + uint32_t code = 0; + + while (code < XKB_KEYCODE_MAX) + { + /* Supress exceptions from unsupported keycodes */ + try + { + if (keymap.XBMCKeysymForKeycode(code) == sym) + return code; + } + catch (std::runtime_error &err) + { + } + + ++code; + } + + throw std::logic_error("Keysym has no corresponding keycode"); +} + +uint32_t LookupModifierIndexForModifier(ILinuxKeymap &keymap, + XBMCMod modifier) +{ + uint32_t maxIndex = std::numeric_limits::max(); + uint32_t index = 0; + + while (index < maxIndex) + { + keymap.UpdateMask(1 << index, 0, 0, 0); + XBMCMod mask = static_cast(keymap.ActiveXBMCModifiers()); + keymap.UpdateMask(0, 0, 0, 0); + if (mask & modifier) + return index; + + ++index; + } + + throw std::logic_error("Modifier has no corresponding keymod index"); +} +} + +TYPED_TEST_P(InputEventQueueWestonTest, KeyEvent) +{ + typedef InputEventsWestonTest Base; + + const unsigned int oKeycode = LookupKeycodeForKeysym(*Base::keymap, + XBMCK_o); + + Base::xbmcWayland->GiveSurfaceKeyboardFocus(Base::surface->GetWlSurface()); + Base::xbmcWayland->SendKeyToKeyboard(Base::surface->GetWlSurface(), + oKeycode, + WL_KEYBOARD_KEY_STATE_PRESSED); + Base::WaitForSynchronize(); + + XBMC_Event event(Base::listener.FetchLastEvent()); + EXPECT_EQ(XBMC_KEYDOWN, event.type); + EXPECT_EQ(oKeycode, event.key.keysym.scancode); + EXPECT_EQ(XBMCK_o, event.key.keysym.sym); + EXPECT_EQ(XBMCK_o, event.key.keysym.unicode); +} + +TYPED_TEST_P(InputEventQueueWestonTest, RepeatAfter1000Ms) +{ + typedef InputEventsWestonTest Base; + + const unsigned int oKeycode = LookupKeycodeForKeysym(*Base::keymap, + XBMCK_o); + + Base::xbmcWayland->GiveSurfaceKeyboardFocus(Base::surface->GetWlSurface()); + Base::xbmcWayland->SendKeyToKeyboard(Base::surface->GetWlSurface(), + oKeycode, + WL_KEYBOARD_KEY_STATE_PRESSED); + Base::WaitForSynchronize(); + ::usleep(1100000); // 1100ms + Base::xbmcWayland->SendKeyToKeyboard(Base::surface->GetWlSurface(), + oKeycode, + WL_KEYBOARD_KEY_STATE_RELEASED); + Base::WaitForSynchronize(); + + /* Throw away first key down */ + XBMC_Event event(Base::listener.FetchLastEvent()); + + /* Synthetic key up should be generated */ + event = Base::listener.FetchLastEvent(); + EXPECT_EQ(XBMC_KEYUP, event.type); + EXPECT_EQ(oKeycode, event.key.keysym.scancode); + + /* Synthetic key down should be generated */ + event = Base::listener.FetchLastEvent(); + EXPECT_EQ(XBMC_KEYDOWN, event.type); + EXPECT_EQ(oKeycode, event.key.keysym.scancode); +} + +TYPED_TEST_P(InputEventQueueWestonTest, NoRepeatAfterRelease) +{ + typedef InputEventsWestonTest Base; + + const unsigned int oKeycode = LookupKeycodeForKeysym(*Base::keymap, + XBMCK_o); + + Base::xbmcWayland->GiveSurfaceKeyboardFocus(Base::surface->GetWlSurface()); + Base::xbmcWayland->SendKeyToKeyboard(Base::surface->GetWlSurface(), + oKeycode, + WL_KEYBOARD_KEY_STATE_PRESSED); + Base::WaitForSynchronize(); + ::usleep(1100000); // 1100ms + Base::xbmcWayland->SendKeyToKeyboard(Base::surface->GetWlSurface(), + oKeycode, + WL_KEYBOARD_KEY_STATE_RELEASED); + Base::WaitForSynchronize(); + + /* Drain any residual events */ + bool eventsPending = true; + while (eventsPending) + { + try + { + Base::listener.FetchLastEvent(); + } + catch (std::logic_error &err) + { + eventsPending = false; + } + } + + /* Sleep-wait again */ + ::usleep(1100000); // 1100ms + Base::WaitForSynchronize(); + + /* Should not be any more events */ + EXPECT_THROW({ Base::listener.FetchLastEvent(); }, std::logic_error); +} + +TYPED_TEST_P(InputEventQueueWestonTest, Modifiers) +{ + typedef InputEventsWestonTest Base; + + const unsigned int oKeycode = LookupKeycodeForKeysym(*Base::keymap, + XBMCK_o); + const unsigned int leftShiftIndex = + LookupModifierIndexForModifier(*Base::keymap, XBMCKMOD_LSHIFT); + + Base::xbmcWayland->GiveSurfaceKeyboardFocus(Base::surface->GetWlSurface()); + Base::xbmcWayland->SendModifiersToKeyboard(Base::surface->GetWlSurface(), + 1 << leftShiftIndex, + 0, + 0, + 0); + Base::xbmcWayland->SendKeyToKeyboard(Base::surface->GetWlSurface(), + oKeycode, + WL_KEYBOARD_KEY_STATE_PRESSED); + Base::WaitForSynchronize(); + + XBMC_Event event(Base::listener.FetchLastEvent()); + EXPECT_EQ(XBMC_KEYDOWN, event.type); + EXPECT_EQ(oKeycode, event.key.keysym.scancode); + EXPECT_TRUE((XBMCKMOD_LSHIFT & event.key.keysym.mod) != 0); +} + +REGISTER_TYPED_TEST_CASE_P(InputEventQueueWestonTest, + Construction, + MotionEvent, + ButtonEvent, + AxisEvent, + KeyEvent, + RepeatAfter1000Ms, + NoRepeatAfterRelease, + Modifiers); + +typedef ::testing::Types= WAYLAND_VERSION_CHECK(1, 1, 90)) + xw::version_11::EventQueueStrategy, + xw::version_12::EventQueueStrategy> EventQueueTypes; +#else + xw::version_11::EventQueueStrategy> EventQueueTypes; +#endif + +INSTANTIATE_TYPED_TEST_CASE_P(EventQueues, + InputEventQueueWestonTest, + EventQueueTypes); diff --git a/xbmc/windowing/tests/wayland/TmpEnv.cpp b/xbmc/windowing/tests/wayland/TmpEnv.cpp new file mode 100644 index 0000000000000..7f3c74f9236af --- /dev/null +++ b/xbmc/windowing/tests/wayland/TmpEnv.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "TmpEnv.h" + +TmpEnv::TmpEnv(const char *env, + const char *val) : + m_env(env), + m_previous(getenv(env)) +{ + setenv(env, val, 1); +} + +TmpEnv::~TmpEnv() +{ + if (m_previous) + setenv(m_env, m_previous, 1); + else + unsetenv(m_env); +} diff --git a/xbmc/windowing/tests/wayland/TmpEnv.h b/xbmc/windowing/tests/wayland/TmpEnv.h new file mode 100644 index 0000000000000..7f67af4c2fdb1 --- /dev/null +++ b/xbmc/windowing/tests/wayland/TmpEnv.h @@ -0,0 +1,36 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +class TmpEnv : + boost::noncopyable +{ +public: + + TmpEnv(const char *env, const char *val); + ~TmpEnv(); + +private: + + const char *m_env; + const char *m_previous; +}; diff --git a/xbmc/windowing/tests/wayland/WestonProcess.cpp b/xbmc/windowing/tests/wayland/WestonProcess.cpp new file mode 100644 index 0000000000000..abc5071c177b4 --- /dev/null +++ b/xbmc/windowing/tests/wayland/WestonProcess.cpp @@ -0,0 +1,566 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "Util.h" + +#include "WestonProcess.h" + +namespace xt = xbmc::test; + +namespace +{ +std::string +FindBinaryFromPATH(const std::string &binary) +{ + const char *pathEnvironmentCArray = getenv("PATH"); + if (!pathEnvironmentCArray) + throw std::runtime_error("PATH is not set"); + + std::string pathEnvironment(pathEnvironmentCArray); + + typedef boost::char_separator CharSeparator; + typedef boost::tokenizer CharTokenizer; + + CharTokenizer paths(pathEnvironment, + CharSeparator(":")); + + for (CharTokenizer::iterator it = paths.begin(); + it != paths.end(); + ++it) + { + std::stringstream possibleBinaryLocationStream; + possibleBinaryLocationStream << *it + << "/" + << binary; + std::string possibleBinaryLocation(possibleBinaryLocationStream.str()); + int ok = access(possibleBinaryLocation.c_str(), X_OK); + + if (ok == -1) + { + switch (errno) + { + case EACCES: + case ENOENT: + continue; + default: + throw std::runtime_error(strerror(errno)); + } + } + + return possibleBinaryLocation; + } + + std::stringstream ss; + ss << "Unable to find " + << binary + << " in PATH as it does not exist or is not executable"; + + throw std::runtime_error(ss.str()); +} +} + +xt::Process::Process(const westring &xbmcTestBase, + const westring &tempFileName) : + m_pid(0) +{ + std::stringstream socketOptionStream; + socketOptionStream << "--socket="; + socketOptionStream << tempFileName.c_str(); + + std::string socketOption(socketOptionStream.str()); + + std::stringstream modulesOptionStream; + modulesOptionStream << "--modules="; + modulesOptionStream << xbmcTestBase.c_str(); + modulesOptionStream << "xbmc/windowing/tests/wayland/xbmc-wayland-test-extension.so"; + + std::string modulesOption(modulesOptionStream.str()); + + std::string program(FindBinaryFromPATH("weston")); + const char *options[] = + { + program.c_str(), + "--backend=headless-backend.so", + modulesOption.c_str(), + socketOption.c_str(), + NULL + }; + + m_pid = fork(); + + switch (m_pid) + { + case 0: + Child(program.c_str(), + const_cast (options)); + case -1: + ForkError(); + default: + Parent(); + } +} + +pid_t +xt::Process::Pid() +{ + return m_pid; +} + +void +xt::Process::Child(const char *program, + char * const *options) +{ + ::signal(SIGUSR2, SIG_IGN); + + /* Unblock SIGUSR2 */ + sigset_t signalMask; + sigemptyset(&signalMask); + sigaddset(&signalMask, SIGUSR2); + if (sigprocmask(SIG_UNBLOCK, &signalMask, NULL)) + { + std::stringstream ss; + ss << "sigprocmask: " << strerror(errno); + throw std::runtime_error(ss.str()); + } + + if (!getenv("XBMC_WESTON_GTEST_CHILD_STDOUT")) + { + ::close(STDOUT_FILENO); + ::close(STDERR_FILENO); + } + + if (execvpe(program, options, environ) == -1) + { + std::stringstream ss; + ss << "execvpe: " << strerror(errno); + throw std::runtime_error(ss.str()); + } +} + +void +xt::Process::Parent() +{ +} + +void +xt::Process::ForkError() +{ + std::stringstream ss; + ss << "fork: " + << strerror(errno); + throw std::runtime_error(ss.str()); +} + +void +xt::Process::WaitForSignal(int signal, int timeout) +{ + sigset_t signalMask; + + if (timeout >= 0) + { + static const uint32_t MsecToNsec = 1000000; + static const uint32_t SecToMsec = 1000; + int seconds = timeout / SecToMsec; + + /* Remove seconds from timeout */ + timeout -= seconds * SecToMsec; + struct timespec ts = { seconds, timeout * MsecToNsec }; + + sigemptyset(&signalMask); + sigaddset(&signalMask, signal); + int received = 0; + + do + { + errno = 0; + received = sigtimedwait(&signalMask, + NULL, + &ts); + if (received == -1) + { + /* Just retry if we got signalled */ + if (errno != EINTR) + { + std::stringstream ss; + ss << "sigtimedwait: " + << strerror(errno); + + throw std::runtime_error(ss.str()); + } + } + } while (errno != 0); + + return; + } + else + { + sigemptyset(&signalMask); + sigaddset(&signalMask, signal); + errno = 0; + int received = sigwaitinfo(&signalMask, NULL); + + if (received != signal) + { + std::stringstream ss; + ss << "sigwaitinfo: " + << strerror(errno); + } + } +} + +namespace +{ +void +WestonMisbehaviourMessage(std::stringstream &ss) +{ + ss << std::endl; + ss << "It is possible that Weston is just shutting down uncleanly " + << " - you should check the stacktrace and run with " + << " ALLOW_WESTON_MISBEHAVIOUR set to suppress this"; +} + +bool +NoMisbehaviour() +{ + return !getenv("ALLOW_WESTON_MISBEHAVIOUR"); +} + +class StatusWaitTimeoutError : + public std::exception +{ +public: + + StatusWaitTimeoutError(int expected, int timeout); + ~StatusWaitTimeoutError() throw() {} + +private: + + const char * what() const throw(); + + int m_expected; + int m_timeout; + + mutable std::string m_what; +}; + +class TerminatedBySignalError : + public std::exception +{ +public: + + TerminatedBySignalError(int expected, int signal); + ~TerminatedBySignalError() throw() {} + +private: + + const char * what() const throw(); + + int m_expected; + int m_signal; + + mutable std::string m_what; +}; + +class AbnormalExitStatusError : + public std::exception +{ +public: + + AbnormalExitStatusError(int expected, int status); + ~AbnormalExitStatusError() throw() {} + +private: + + const char * what() const throw(); + + int m_expected; + int m_status; + + mutable std::string m_what; +}; + +StatusWaitTimeoutError::StatusWaitTimeoutError(int expected, + int timeout) : + m_expected(expected), + m_timeout(timeout) +{ +} + +const char * +StatusWaitTimeoutError::what() const throw() +{ + std::stringstream ss; + ss << "Expected exit status " + << m_expected + << " within " + << m_timeout + << " ms"; + m_what = ss.str(); + return m_what.c_str(); +} + +TerminatedBySignalError::TerminatedBySignalError(int expected, + int signal) : + m_expected(expected), + m_signal(signal) +{ +} + +const char * +TerminatedBySignalError::what() const throw() +{ + std::stringstream ss; + ss << "Expected exit status " + << m_expected + << " but was instead terminated by signal " + << m_signal + << " - " + << strsignal(m_signal); + WestonMisbehaviourMessage(ss); + m_what = ss.str(); + return m_what.c_str(); +} + +AbnormalExitStatusError::AbnormalExitStatusError(int expected, + int status) : + m_expected(expected), + m_status(status) +{ +} + +const char * +AbnormalExitStatusError::what() const throw() +{ + std::stringstream ss; + ss << "Expected exit status " + << m_expected + << " but instead exited with " + << m_status + << " - " + << strsignal(m_status); + WestonMisbehaviourMessage(ss); + m_what = ss.str(); + return m_what.c_str(); +} +} + +void +xt::Process::WaitForStatus(int code, int timeout) +{ + struct timespec startTime; + struct timespec currentTime; + clock_gettime(CLOCK_MONOTONIC, &startTime); + clock_gettime(CLOCK_MONOTONIC, ¤tTime); + + const uint32_t SecToMsec = 1000; + const uint32_t MsecToNsec = 1000000; + + int32_t startTimestamp = startTime.tv_sec * SecToMsec + + startTime.tv_nsec / MsecToNsec; + int32_t currentTimestamp = currentTime.tv_sec * SecToMsec + + currentTime.tv_nsec / MsecToNsec; + + int options = WUNTRACED; + + std::stringstream statusMessage; + + if (timeout >= 0) + options |= WNOHANG; + + do + { + clock_gettime(CLOCK_MONOTONIC, ¤tTime); + + currentTimestamp = currentTime.tv_sec * SecToMsec + + currentTime.tv_nsec / MsecToNsec; + + int returnedStatus; + pid_t pid = waitpid(m_pid, &returnedStatus, options); + + if (pid == m_pid) + { + /* At least one child has exited */ + if (WIFEXITED(returnedStatus)) + { + int returnedExitCode = WEXITSTATUS(returnedStatus); + if (returnedExitCode == code) + return; + + /* Abnormal exit status */ + throw AbnormalExitStatusError(code, returnedExitCode); + } + else if (WIFSIGNALED(returnedStatus)) + { + int returnedSignal = WTERMSIG(returnedStatus); + + /* Signaled and died */ + throw TerminatedBySignalError(code, returnedSignal); + } + } + else if (pid == -1) + { + std::stringstream ss; + ss << "waitpid failed: " + << strerror(errno); + throw std::runtime_error(ss.str()); + } + else if (!pid) + { + struct timespec ts; + ts.tv_sec = 0; + + /* Don't sleep the whole time, we might have just missed + * the signal */ + ts.tv_nsec = timeout * MsecToNsec / 10; + + nanosleep(&ts, NULL); + } + } + while (timeout == -1 || + (timeout > currentTimestamp - startTimestamp)); + + /* If we didn't get out early, it means we timed out */ + throw StatusWaitTimeoutError(code, timeout); +} + +void +xt::Process::SendSignal(int signal) +{ + if (kill(m_pid, signal) == -1) + { + /* Already dead ... lets see if it exited normally */ + if (errno == ESRCH) + { + try + { + WaitForStatus(0, 0); + } + catch (std::runtime_error &err) + { + std::stringstream ss; + ss << err.what() + << " - process was already dead" + << std::endl; + throw std::runtime_error(ss.str()); + } + } + else + { + std::stringstream ss; + ss << "failed to send signal " + << signal + << " to process " + << m_pid + << ": " << strerror(errno); + throw std::runtime_error(ss.str()); + } + } +} + +void +xt::Process::Interrupt() +{ + SendSignal(SIGINT); +} + +void +xt::Process::Terminate() +{ + SendSignal(SIGTERM); +} + +void +xt::Process::Kill() +{ + SendSignal(SIGKILL); +} + +xt::Process::~Process() +{ + typedef void (Process::*SignalAction)(void); + SignalAction deathActions[] = + { + &Process::Interrupt, + &Process::Terminate, + &Process::Kill + }; + + static const size_t deathActionsSize = sizeof(deathActions) / + sizeof(deathActions[0]); + + size_t i = 0; + + std::stringstream processStatusMessages; + + for (; i < deathActionsSize; ++i) + { + try + { + SignalAction func(deathActions[i]); + ((*this).*(func))(); + WaitForStatus(0, DefaultProcessWaitTimeout); + break; + } + catch (const TerminatedBySignalError &err) + { + if (NoMisbehaviour()) + throw; + else + break; + } + catch (const AbnormalExitStatusError &err) + { + if (NoMisbehaviour()) + throw; + else + break; + } + catch (const StatusWaitTimeoutError &err) + { + processStatusMessages << "[TIMEOUT] " + << static_cast(err).what() + << std::endl; + } + } + + if (i == deathActionsSize) + { + std::stringstream ss; + ss << "Failed to terminate " + << m_pid + << std::endl; + ss << processStatusMessages; + throw std::runtime_error(ss.str()); + } +} + + + diff --git a/xbmc/windowing/tests/wayland/WestonProcess.h b/xbmc/windowing/tests/wayland/WestonProcess.h new file mode 100644 index 0000000000000..6d923cf37c3a8 --- /dev/null +++ b/xbmc/windowing/tests/wayland/WestonProcess.h @@ -0,0 +1,70 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "system.h" + +#include + +#ifdef UNICODE + typedef std::wstring westring; +#else + typedef std::string westring; +#endif + +typedef int32_t pid_t; + +namespace xbmc +{ +namespace test +{ +class Process : + boost::noncopyable +{ +public: + + Process(const westring &base, + const westring &socket); + ~Process(); + + void WaitForSignal(int signal, int timeout); + void WaitForStatus(int status, int timeout); + + void Interrupt(); + void Terminate(); + void Kill(); + + pid_t Pid(); + + static const int DefaultProcessWaitTimeout = 3000; // 3000ms + +private: + + void SendSignal(int signal); + + void Child(const char *program, + char * const *options); + void ForkError(); + void Parent(); + + pid_t m_pid; +}; +} +} diff --git a/xbmc/windowing/tests/wayland/WestonTest.cpp b/xbmc/windowing/tests/wayland/WestonTest.cpp new file mode 100644 index 0000000000000..d962a588983e4 --- /dev/null +++ b/xbmc/windowing/tests/wayland/WestonTest.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include + +#include + +#include "test/TestUtils.h" +#include "utils/log.h" + +#include "TmpEnv.h" +#include "WestonProcess.h" +#include "WestonTest.h" + +namespace xt = xbmc::test; + +namespace +{ +class TempFileWrapper : + boost::noncopyable +{ +public: + + TempFileWrapper(const westring &suffix); + ~TempFileWrapper(); + + void FetchDirectory(westring &directory); + void FetchFilename(westring &name); +private: + + XFILE::CFile *m_file; +}; + +TempFileWrapper::TempFileWrapper(const westring &suffix) : + m_file(CXBMCTestUtils::Instance().CreateTempFile(suffix)) +{ +} + +TempFileWrapper::~TempFileWrapper() +{ + CXBMCTestUtils::Instance().DeleteTempFile(m_file); +} + +void TempFileWrapper::FetchDirectory(westring &directory) +{ + directory = CXBMCTestUtils::Instance().TempFileDirectory(m_file); + /* Strip trailing "/" */ + directory.resize(directory.size() - 1); +} + +void TempFileWrapper::FetchFilename(westring &name) +{ + westring path(CXBMCTestUtils::Instance().TempFilePath(m_file)); + westring directory(CXBMCTestUtils::Instance().TempFileDirectory(m_file)); + + name = path.substr(directory.size()); +} + +class SavedTempSocket : + boost::noncopyable +{ +public: + + SavedTempSocket(); + + const westring & FetchFilename(); + const westring & FetchDirectory(); + +private: + + westring m_filename; + westring m_directory; +}; + +SavedTempSocket::SavedTempSocket() +{ + TempFileWrapper wrapper(""); + wrapper.FetchDirectory(m_directory); + wrapper.FetchFilename(m_filename); +} + +const westring & +SavedTempSocket::FetchFilename() +{ + return m_filename; +} + +const westring & +SavedTempSocket::FetchDirectory() +{ + return m_directory; +} + +template +class SignalGuard : + boost::noncopyable +{ +public: + + SignalGuard(const Iterator &begin, + const Iterator &end); + ~SignalGuard(); +private: + + sigset_t mask; +}; + +template +SignalGuard::SignalGuard(const Iterator &begin, + const Iterator &end) +{ + sigemptyset(&mask); + for (Iterator it = begin; + it != end; + ++it) + sigaddset(&mask, *it); + + if (sigprocmask(SIG_BLOCK, &mask, NULL)) + { + std::stringstream ss; + ss << "sigprogmask: " + << strerror(errno); + throw std::runtime_error(ss.str()); + } +} + +template +SignalGuard::~SignalGuard() +{ + if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) + CLog::Log(LOGERROR, "Failed to unblock signals"); +} + +typedef boost::array SigArray; +SigArray BlockedSignals = +{ + { + SIGUSR2, + SIGCHLD + } +}; +} + +class WestonTest::Private +{ +public: + + Private(); + ~Private(); + + westring m_xbmcTestBase; + SavedTempSocket m_tempSocketName; + TmpEnv m_xdgRuntimeDir; + + SignalGuard m_signalGuard; + + xt::Process m_process; +}; + +WestonTest::WestonTest() : + priv(new Private()) +{ +} + +/* We need a defined destructor, otherwise we will + * generate the destructors for all of the owned objects + * multiple times where the definitions for those + * destructors is unavailable */ +WestonTest::~WestonTest() +{ +} + +WestonTest::Private::Private() : + m_xbmcTestBase(CXBMCTestUtils::Instance().ReferenceFilePath("")), + /* We want wayland (client and server) to look in our + * temp file directory for the socket */ + m_xdgRuntimeDir("XDG_RUNTIME_DIR", m_tempSocketName.FetchDirectory().c_str()), + /* Block emission of SIGUSR2 so that we can wait on it */ + m_signalGuard(BlockedSignals.begin(), BlockedSignals.end()), + m_process(m_xbmcTestBase, + m_tempSocketName.FetchFilename()) +{ +} + +WestonTest::Private::~Private() +{ +} + +pid_t +WestonTest::Pid() +{ + return priv->m_process.Pid(); +} + +const westring & +WestonTest::TempSocketName() +{ + return priv->m_tempSocketName.FetchFilename(); +} + +void +WestonTest::SetUp() +{ + priv->m_process.WaitForSignal(SIGUSR2, xt::Process::DefaultProcessWaitTimeout); +} diff --git a/xbmc/windowing/tests/wayland/WestonTest.h b/xbmc/windowing/tests/wayland/WestonTest.h new file mode 100644 index 0000000000000..5e5548c784be6 --- /dev/null +++ b/xbmc/windowing/tests/wayland/WestonTest.h @@ -0,0 +1,50 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +#ifdef UNICODE + typedef std::wstring westring; +#else + typedef std::string westring; +#endif + +typedef int32_t pid_t; + +class WestonTest : + public ::testing::Test +{ +public: + + WestonTest(); + ~WestonTest(); + pid_t Pid(); + const westring & TempSocketName(); + + virtual void SetUp(); + +private: + + class Private; + boost::scoped_ptr priv; +}; diff --git a/xbmc/windowing/tests/wayland/XBMCWayland.cpp b/xbmc/windowing/tests/wayland/XBMCWayland.cpp new file mode 100644 index 0000000000000..eb17f29646025 --- /dev/null +++ b/xbmc/windowing/tests/wayland/XBMCWayland.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "system.h" + +#if defined(HAVE_WAYLAND_XBMC_PROTO) + +#include +#include +#include "xbmc_wayland_test_client_protocol.h" + +#include "XBMCWayland.h" + +namespace xtw = xbmc::test::wayland; + +xtw::XBMCWayland::XBMCWayland(struct xbmc_wayland *xbmcWayland) : + m_xbmcWayland(xbmcWayland) +{ +} + +xtw::XBMCWayland::~XBMCWayland() +{ + xbmc_wayland_destroy(m_xbmcWayland); +} + +void +xtw::XBMCWayland::AddMode(int width, + int height, + uint32_t refresh, + enum wl_output_mode flags) +{ + xbmc_wayland_add_mode(m_xbmcWayland, + width, + height, + refresh, + static_cast(flags)); +} + +void +xtw::XBMCWayland::MovePointerTo(struct wl_surface *surface, + wl_fixed_t x, + wl_fixed_t y) +{ + xbmc_wayland_move_pointer_to_on_surface(m_xbmcWayland, + surface, + x, + y); +} + +void +xtw::XBMCWayland::SendButtonTo(struct wl_surface *surface, + uint32_t button, + uint32_t state) +{ + xbmc_wayland_send_button_to_surface(m_xbmcWayland, + surface, + button, + state); +} + +void +xtw::XBMCWayland::SendAxisTo(struct wl_surface *surface, + uint32_t axis, + wl_fixed_t value) +{ + xbmc_wayland_send_axis_to_surface(m_xbmcWayland, + surface, + axis, + value); +} + +void +xtw::XBMCWayland::SendKeyToKeyboard(struct wl_surface *surface, + uint32_t key, + enum wl_keyboard_key_state state) +{ + xbmc_wayland_send_key_to_keyboard(m_xbmcWayland, + surface, + key, + state); +} + +void +xtw::XBMCWayland::SendModifiersToKeyboard(struct wl_surface *surface, + uint32_t depressed, + uint32_t latched, + uint32_t locked, + uint32_t group) +{ + xbmc_wayland_send_modifiers_to_keyboard(m_xbmcWayland, + surface, + depressed, + latched, + locked, + group); +} + +void +xtw::XBMCWayland::GiveSurfaceKeyboardFocus(struct wl_surface *surface) +{ + xbmc_wayland_give_surface_keyboard_focus(m_xbmcWayland, + surface); +} + +void +xtw::XBMCWayland::PingSurface(struct wl_surface *surface, + uint32_t serial) +{ + xbmc_wayland_ping_surface(m_xbmcWayland, surface, serial); +} + +#endif diff --git a/xbmc/windowing/tests/wayland/XBMCWayland.h b/xbmc/windowing/tests/wayland/XBMCWayland.h new file mode 100644 index 0000000000000..1a5545f89bd58 --- /dev/null +++ b/xbmc/windowing/tests/wayland/XBMCWayland.h @@ -0,0 +1,78 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#if defined(HAVE_WAYLAND_XBMC_PROTO) + +#include + +struct wl_surface; +struct xbmc_wayland; + +namespace xbmc +{ +namespace test +{ +namespace wayland +{ +class XBMCWayland : + boost::noncopyable +{ +public: + + XBMCWayland(struct xbmc_wayland *xbmcWayland); + ~XBMCWayland(); + + struct wl_surface * MostRecentSurface(); + + void AddMode(int width, + int height, + uint32_t refresh, + enum wl_output_mode mode); + void MovePointerTo(struct wl_surface *surface, + wl_fixed_t x, + wl_fixed_t y); + void SendButtonTo(struct wl_surface *surface, + uint32_t button, + uint32_t state); + void SendAxisTo(struct wl_surface *, + uint32_t axis, + wl_fixed_t value); + void SendKeyToKeyboard(struct wl_surface *surface, + uint32_t key, + enum wl_keyboard_key_state state); + void SendModifiersToKeyboard(struct wl_surface *surface, + uint32_t depressed, + uint32_t latched, + uint32_t locked, + uint32_t group); + void GiveSurfaceKeyboardFocus(struct wl_surface *surface); + void PingSurface (struct wl_surface *surface, + uint32_t serial); + +private: + + struct xbmc_wayland *m_xbmcWayland; +}; +} +} +} + +#endif diff --git a/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp b/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp new file mode 100644 index 0000000000000..90c665abccef7 --- /dev/null +++ b/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp @@ -0,0 +1,792 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "system.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +extern "C" +{ +/* Work around usage of a reserved keyword + * https://bugs.freedesktop.org/show_bug.cgi?id=63485 */ +#define private cprivate +#include +#undef private +#include +#include "xbmc_wayland_test_server_protocol.h" +} + +namespace xbmc +{ +namespace test +{ +namespace wayland +{ +class Listener : + boost::noncopyable +{ +public: + + typedef boost::function Delegate; + + Listener(const Delegate &); + void BindTo(struct wl_signal *); + +private: + + static void MainCallback(struct wl_listener *listener, void *data); + + void Callback(); + + struct wl_listener m_listener; + Delegate m_delegate; +}; +} + +namespace weston +{ +class Compositor : + boost::noncopyable +{ +public: + + Compositor(struct weston_compositor *); + ~Compositor(); + + struct wl_display * Display(); + + struct weston_surface * TopSurface(); + struct weston_mode * LastMode(); + void OnEachMode(const boost::function &); + struct wl_resource * PointerResource(struct wl_client *client); + struct wl_resource * KeyboardResource(struct wl_client *client); + struct weston_surface * Surface(struct wl_resource *client); + struct weston_keyboard * Keyboard(); + +private: + + static void Unload(Compositor *compositor); + static int Ready(void *); + + struct weston_compositor *m_compositor; + struct wl_event_source *m_readySource; + wayland::Listener m_destroyListener; + struct weston_seat * Seat(); + struct weston_output * FirstOutput(); +}; +} + +namespace wayland +{ +class XBMCWayland : + boost::noncopyable +{ +public: + + ~XBMCWayland(); + + struct wl_resource * GetResource(); + + /* Effectively a factory function for XBMCWayland. Creates an + * instantiation for a client */ + static void BindToClient(struct wl_client *client, + void *data, + uint32_t version, + uint32_t id); + +private: + + /* Constructor is private as this object may only be constructed + * by a client binding to its interface */ + XBMCWayland(struct wl_client *client, + uint32_t id, + weston::Compositor &compositor); + + static void UnbindFromClientCallback(struct wl_resource *); + + static const struct xbmc_wayland_interface m_listener; + + static void AddModeCallback(struct wl_client *, + struct wl_resource *, + int32_t, + int32_t, + uint32_t, + uint32_t); + static void MovePointerToOnSurfaceCallback(struct wl_client *, + struct wl_resource *, + struct wl_resource *, + wl_fixed_t x, + wl_fixed_t y); + static void SendButtonToSurfaceCallback(struct wl_client *, + struct wl_resource *, + struct wl_resource *, + uint32_t, + uint32_t); + static void SendAxisToSurfaceCallback(struct wl_client *, + struct wl_resource *, + struct wl_resource *, + uint32_t, + wl_fixed_t); + static void SendKeyToKeyboardCallback(struct wl_client *, + struct wl_resource *, + struct wl_resource *, + uint32_t, + uint32_t); + static void SendModifiersToKeyboardCallback(struct wl_client *, + struct wl_resource *, + struct wl_resource *, + uint32_t, + uint32_t, + uint32_t, + uint32_t); + static void GiveSurfaceKeyboardFocusCallback(struct wl_client *, + struct wl_resource *, + struct wl_resource *); + static void PingSurfaceCallback(struct wl_client *, + struct wl_resource *, + struct wl_resource *, + uint32_t timestamp); + + void AddMode(struct wl_client *client, + struct wl_resource *resource, + int32_t width, + int32_t height, + uint32_t refresh, + uint32_t flags); + void MovePointerToOnSurface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + wl_fixed_t x, + wl_fixed_t y); + void SendButtonToSurface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + uint32_t button, + uint32_t state); + void SendAxisToSurface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + uint32_t axis, + wl_fixed_t value); + void SendKeyToKeyboard(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surfaceResource, + uint32_t key, + uint32_t state); + void SendModifiersToKeyboard(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surfaceResource, + uint32_t depressed, + uint32_t latched, + uint32_t locked, + uint32_t group); + void GiveSurfaceKeyboardFocus(struct wl_client *clent, + struct wl_resource *resource, + struct wl_resource *surfaceResource); + void PingSurface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surfaceResource, + uint32_t timestamp); + + weston::Compositor &m_compositor; + struct wl_resource *m_clientXBMCWaylandResource; + + std::vector m_additionalModes; +}; + +const struct xbmc_wayland_interface XBMCWayland::m_listener = +{ + XBMCWayland::AddModeCallback, + XBMCWayland::MovePointerToOnSurfaceCallback, + XBMCWayland::SendButtonToSurfaceCallback, + XBMCWayland::SendAxisToSurfaceCallback, + XBMCWayland::SendKeyToKeyboardCallback, + XBMCWayland::SendModifiersToKeyboardCallback, + XBMCWayland::GiveSurfaceKeyboardFocusCallback, + XBMCWayland::PingSurfaceCallback +}; +} +} +} + +namespace xtw = xbmc::test::wayland; +namespace xtwc = xbmc::test::weston; + +xtw::XBMCWayland::XBMCWayland(struct wl_client *client, + uint32_t id, + xtwc::Compositor &compositor) : + m_compositor(compositor) +{ + m_clientXBMCWaylandResource = + static_cast(wl_resource_create(client, + &xbmc_wayland_interface, + 1, + id)); + wl_resource_set_implementation (m_clientXBMCWaylandResource, + &m_listener, + this, + XBMCWayland::UnbindFromClientCallback); +} + +xtw::XBMCWayland::~XBMCWayland() +{ + /* Remove all but the first output if we added any */ + for (std::vector::iterator it = m_additionalModes.begin(); + it != m_additionalModes.end(); + ++it) + { + wl_list_remove(&it->link); + } +} + +void +xtw::XBMCWayland::UnbindFromClientCallback(struct wl_resource *r) +{ + delete static_cast(wl_resource_get_user_data(r)); +} + +void +xtw::XBMCWayland::BindToClient(struct wl_client *client, + void *data, + uint32_t version, + uint32_t id) +{ + xtwc::Compositor *compositor = static_cast(data); + + /* This looks funky - however the constructor will handle registering + * the destructor function with wl_registry so that it gets destroyed + * at the right time */ + new XBMCWayland(client, id, *compositor); +} + +void +xtw::XBMCWayland::AddModeCallback(struct wl_client *c, + struct wl_resource *r, + int32_t w, + int32_t h, + uint32_t re, + uint32_t f) +{ + static_cast(wl_resource_get_user_data(r))->AddMode(c, r, w, h, re, f); +} + +void +xtw::XBMCWayland::MovePointerToOnSurfaceCallback(struct wl_client *c, + struct wl_resource *r, + struct wl_resource *s, + wl_fixed_t x, + wl_fixed_t y) +{ + static_cast(wl_resource_get_user_data(r))->MovePointerToOnSurface(c, r, s, x, y); +} + +void +xtw::XBMCWayland::SendButtonToSurfaceCallback(struct wl_client *c, + struct wl_resource *r, + struct wl_resource *s, + uint32_t b, + uint32_t st) +{ + static_cast(wl_resource_get_user_data(r))->SendButtonToSurface(c, r, s, b, st); +} + +void +xtw::XBMCWayland::SendAxisToSurfaceCallback(struct wl_client *c, + struct wl_resource *r, + struct wl_resource *s, + uint32_t b, + wl_fixed_t v) +{ + static_cast(wl_resource_get_user_data(r))->SendAxisToSurface(c, r, s, b, v); +} + +void +xtw::XBMCWayland::SendModifiersToKeyboardCallback(struct wl_client *c, + struct wl_resource *r, + struct wl_resource *s, + uint32_t d, + uint32_t la, + uint32_t lo, + uint32_t g) +{ + static_cast(wl_resource_get_user_data(r))->SendModifiersToKeyboard(c, r, s, d, la, lo, g); +} + +void +xtw::XBMCWayland::SendKeyToKeyboardCallback(struct wl_client *c, + struct wl_resource *r, + struct wl_resource *s, + uint32_t k, + uint32_t st) +{ + static_cast(wl_resource_get_user_data(r))->SendKeyToKeyboard(c, r, s, k, st); +} + +void +xtw::XBMCWayland::GiveSurfaceKeyboardFocusCallback(struct wl_client *c, + struct wl_resource *r, + struct wl_resource *s) +{ + static_cast(wl_resource_get_user_data(r))->GiveSurfaceKeyboardFocus(c, r, s); +} + +void +xtw::XBMCWayland::PingSurfaceCallback(struct wl_client *c, + struct wl_resource *r, + struct wl_resource *s, + uint32_t t) +{ + static_cast(wl_resource_get_user_data(r))->PingSurface(c, r, s, t); +} + +namespace +{ +void ClearFlagsOnOtherModes(struct weston_mode *mode, + uint32_t flags, + struct weston_mode *skip) +{ + if (mode == skip) + return; + + mode->flags &= ~flags; +} +} + +void +xtw::XBMCWayland::AddMode(struct wl_client *client, + struct wl_resource *resource, + int32_t width, + int32_t height, + uint32_t refresh, + uint32_t flags) +{ + const struct weston_mode mode = + { + flags, + width, + height, + refresh + }; + + m_additionalModes.push_back(mode); + struct weston_mode *lastMode = m_compositor.LastMode(); + wl_list_insert(&lastMode->link, &m_additionalModes.back().link); + + /* Clear flags from all other outputs that may have the same flags + * as this one */ + m_compositor.OnEachMode(boost::bind(ClearFlagsOnOtherModes, + _1, + flags, + &m_additionalModes.back())); +} + +namespace +{ +void GetSerialAndTime(struct wl_display *display, + uint32_t &serial, + uint32_t &time) +{ + serial = wl_display_next_serial(display); + + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + time = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; +} +} + +void +xtw::XBMCWayland::MovePointerToOnSurface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + wl_fixed_t x, + wl_fixed_t y) +{ + struct wl_client *surfaceClient = wl_resource_get_client(surface); + struct wl_resource *pointer = m_compositor.PointerResource(surfaceClient); + struct wl_display *display = wl_client_get_display(surfaceClient); + uint32_t serial, time; + + GetSerialAndTime(display, serial, time); + + wl_pointer_send_motion(pointer, time, x, y); +} + +void +xtw::XBMCWayland::SendButtonToSurface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + uint32_t button, + uint32_t state) +{ + struct wl_client *surfaceClient = wl_resource_get_client(surface); + struct wl_resource *pointer = m_compositor.PointerResource(surfaceClient); + struct wl_display *display = wl_client_get_display(surfaceClient); + uint32_t serial, time; + + GetSerialAndTime(display, serial, time); + + wl_pointer_send_button(pointer, serial, time, button, state); +} + +void +xtw::XBMCWayland::SendAxisToSurface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + uint32_t axis, + wl_fixed_t value) +{ + struct wl_client *surfaceClient = wl_resource_get_client(surface); + struct wl_resource *pointer = m_compositor.PointerResource(surfaceClient); + struct wl_display *display = wl_client_get_display(surfaceClient); + uint32_t serial, time; + + GetSerialAndTime(display, serial, time); + + wl_pointer_send_axis(pointer, time, axis, value); +} + +void +xtw::XBMCWayland::SendKeyToKeyboard(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + uint32_t key, + uint32_t state) +{ + struct wl_client *surfaceClient = wl_resource_get_client(surface); + struct wl_resource *keyboard = m_compositor.KeyboardResource(surfaceClient); + struct wl_display *display = wl_client_get_display(surfaceClient); + uint32_t serial, time; + + GetSerialAndTime(display, serial, time); + + wl_keyboard_send_key(keyboard, serial, time, key, state); +} + +void +xtw::XBMCWayland::SendModifiersToKeyboard(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + uint32_t depressed, + uint32_t latched, + uint32_t locked, + uint32_t group) +{ + struct wl_client *surfaceClient = wl_resource_get_client(surface); + struct wl_resource *keyboard = m_compositor.KeyboardResource(surfaceClient); + struct wl_display *display = wl_client_get_display(surfaceClient); + uint32_t serial = wl_display_next_serial(display); + + wl_keyboard_send_modifiers(keyboard, + serial, + depressed, + latched, + locked, + group); +} + +void +xtw::XBMCWayland::GiveSurfaceKeyboardFocus(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface) +{ + struct weston_surface *westonSurface = m_compositor.Surface(surface); + struct weston_keyboard *keyboard = m_compositor.Keyboard(); + weston_keyboard_set_focus(keyboard, westonSurface); +} + +void +xtw::XBMCWayland::PingSurface(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + uint32_t timestamp) +{ +} + +xtw::Listener::Listener(const Delegate &delegate) : + m_delegate(delegate) +{ + m_listener.notify = Listener::MainCallback; +} + +void +xtw::Listener::MainCallback(struct wl_listener *listener, void *data) +{ + static_cast(data)->Callback(); +} + +void +xtw::Listener::Callback() +{ + m_delegate(); +} + +void +xtw::Listener::BindTo(struct wl_signal *s) +{ + wl_signal_add(s, &m_listener); +} + +xtwc::Compositor::Compositor(struct weston_compositor *c) : + m_compositor(c), + /* This is a workaround for a race condition where the registry + * might not be ready if we send SIGUSR2 right away - so we + * put it on the event loop to happen after the first poll() */ + m_readySource(wl_event_loop_add_timer(wl_display_get_event_loop(Display()), + Compositor::Ready, + this)), + m_destroyListener(boost::bind(Compositor::Unload, this)) +{ + /* Dispatch ASAP */ + wl_event_source_timer_update(m_readySource, 1); + m_destroyListener.BindTo(&c->destroy_signal); + + /* The parent process should have set the SIGUSR2 handler to + * SIG_IGN, throw if it hasn't */ + if (signal(SIGUSR2, SIG_IGN) != SIG_IGN) + { + std::stringstream ss; + throw std::runtime_error("Parent process is not handling SIGUSR2"); + } +} + +int +xtwc::Compositor::Ready(void *data) +{ + xtwc::Compositor *compositor = static_cast(data); + + if (kill(getppid(), SIGUSR2) == -1) + { + std::stringstream ss; + ss << "kill: " + << strerror(errno); + throw std::runtime_error(ss.str()); + } + + wl_event_source_remove(compositor->m_readySource); + compositor->m_readySource = NULL; + + /* Initialize the fake keyboard and pointer on our seat. This is + * effectively manipulating the backend into doing something it + * shouldn't, but we're in control here */ + struct weston_seat *seat = compositor->Seat(); + weston_seat_init_pointer(seat); + + struct xkb_keymap *keymap = + xkb_keymap_new_from_names(compositor->m_compositor->xkb_context, + &compositor->m_compositor->xkb_names, + static_cast(0)); + if (!keymap) + throw std::runtime_error("Failed to compile keymap\n"); + + weston_seat_init_keyboard(seat, keymap); + xkb_keymap_unref(keymap); + return 1; +} + +struct weston_output * +xtwc::Compositor::FirstOutput() +{ + struct weston_output *output; + + output = wl_container_of(m_compositor->output_list.prev, + output, + link); + + return output; +} + +struct wl_display * +xtwc::Compositor::Display() +{ + return m_compositor->wl_display; +} + +struct weston_seat * +xtwc::Compositor::Seat() +{ + /* Since it is impossible to get a weston_seat from a weston_compositor + * and we will need that in order to get access to the weston_pointer + * and weston_keyboard, we need to use this hack to get access + * to the seat by casting the weston_compositor to this, which is + * copied from compositor-headless.c . Since weston_compositor is + * the the first member of headless_compositor, it is safe to cast + * from the second to the first */ + struct headless_compositor { + struct weston_compositor compositor; + struct weston_seat seat; + }; + + /* Before we cast, we should check if we are actually running + * on the headless compositor. If not, throw an exception so + * that the user might know what's going on */ + struct weston_output *output = FirstOutput(); + + if (!output) + throw std::runtime_error("Compositor does not have an output"); + + if (std::string(output->model) != "headless") + { + std::stringstream ss; + ss << "Only the compositor-headless.so backend " + << "is supported by this extension. " + << std::endl + << "The current output model detected was " + << output->model; + throw std::logic_error(ss.str()); + } + + struct headless_compositor *hc = + reinterpret_cast(m_compositor); + + return &hc->seat; +} + +struct weston_surface * +xtwc::Compositor::TopSurface() +{ + struct weston_surface *surface; + + /* The strange semantics of wl_container_of means that we can't + * return its result directly because it needs to have an + * instantiation of the type */ + surface = wl_container_of(m_compositor->surface_list.prev, + surface, + link); + return surface; +} + +void +xtwc::Compositor::OnEachMode(const boost::function &action) +{ + struct weston_output *output = FirstOutput(); + struct weston_mode *mode; + + wl_list_for_each(mode, &output->mode_list, link) + { + action(mode); + } +} + +struct weston_mode * +xtwc::Compositor::LastMode() +{ + struct weston_mode *mode; + struct weston_output *output = FirstOutput(); + mode = wl_container_of(output->mode_list.prev, + mode, + link); + + return mode; +} + +struct wl_resource * +xtwc::Compositor::PointerResource(struct wl_client *client) +{ + struct weston_seat *seat = Seat(); + struct wl_resource *r = + wl_resource_find_for_client(&seat->pointer->focus_resource_list, + client); + if (!r) + r = wl_resource_find_for_client(&seat->pointer->resource_list, + client); + + if (!r) + throw std::logic_error ("No pointer resource available for this " + "client "); + return r; +} + +struct wl_resource * +xtwc::Compositor::KeyboardResource(struct wl_client *client) +{ + struct weston_seat *seat = Seat(); + struct wl_resource *r = + wl_resource_find_for_client(&seat->keyboard->focus_resource_list, + client); + if (!r) + r = wl_resource_find_for_client(&seat->keyboard->resource_list, + client); + + if (!r) + throw std::logic_error ("No keyboard resource available for this " + "client "); + return r; +} + +struct weston_surface * +xtwc::Compositor::Surface(struct wl_resource *surface) +{ + struct weston_surface *ws = + reinterpret_cast(wl_resource_get_user_data(surface)); + + return ws; +} + +void +xtwc::Compositor::Unload(xtwc::Compositor *compositor) +{ + delete compositor; +} + +struct weston_keyboard * +xtwc::Compositor::Keyboard() +{ + struct weston_seat *seat = Seat(); + return seat->keyboard; +} + +xtwc::Compositor::~Compositor() +{ +} + +extern "C" +{ +WL_EXPORT int +module_init(struct weston_compositor *c, + int *argc, + char *argv[]) +{ + /* Using heap allocated memory directly here is awkward, however + * weston knows when we need to destroy our resources + * so we will let it handle it */ + xtwc::Compositor *compositor(new xtwc::Compositor(c)); + /* Register our factory for xbmc_wayland and pass + * xtwc::Compositor to it when it gets created */ + if (wl_global_create(compositor->Display(), + &xbmc_wayland_interface, + 1, + compositor, + xtw::XBMCWayland::BindToClient) == NULL) + return -1; + + return 0; +} +} + diff --git a/xbmc/windowing/tests/wayland/protocol.xml b/xbmc/windowing/tests/wayland/protocol.xml new file mode 100644 index 0000000000000..69f5202eba702 --- /dev/null +++ b/xbmc/windowing/tests/wayland/protocol.xml @@ -0,0 +1,63 @@ + + + + Copyright (C) 2005-2013 Team XBMC + http://www.xbmc.org + + This Program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This Program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with XBMC; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xbmc/windowing/wayland/CursorManager.h b/xbmc/windowing/wayland/CursorManager.h new file mode 100644 index 0000000000000..de6313a093eba --- /dev/null +++ b/xbmc/windowing/wayland/CursorManager.h @@ -0,0 +1,38 @@ +#pragma once + +/* +* Copyright (C) 2005-2013 Team XBMC +* http://xbmc.org +* +* This Program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This Program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with XBMC; see the file COPYING. If not, see +* . +* +*/ +#include + +struct wl_surface; + +namespace xbmc +{ +class ICursorManager +{ +public: + + virtual ~ICursorManager() {} + virtual void SetCursor(uint32_t serial, + struct wl_surface *surface, + double surfaceX, + double surfaceY) = 0; +}; +} diff --git a/xbmc/windowing/wayland/EventListener.h b/xbmc/windowing/wayland/EventListener.h new file mode 100644 index 0000000000000..452083cca1832 --- /dev/null +++ b/xbmc/windowing/wayland/EventListener.h @@ -0,0 +1,40 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "windowing/XBMC_events.h" + +namespace xbmc +{ +/* We inject an IWaylandRegistration here which is a virtual + * class which a series of callbacks for the global objects + * used by xbmc. Once one of those objects becomes + * available, we call the specified callback function on that + * interface */ +class IEventListener +{ +public: + + virtual ~IEventListener() {} + virtual void OnEvent(XBMC_Event &) = 0; + virtual void OnFocused() = 0; + virtual void OnUnfocused() = 0; +}; +} diff --git a/xbmc/windowing/wayland/EventLoop.cpp b/xbmc/windowing/wayland/EventLoop.cpp new file mode 100644 index 0000000000000..5b5ea2a46d33f --- /dev/null +++ b/xbmc/windowing/wayland/EventLoop.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include +#include + +#include "utils/Stopwatch.h" + +#include "EventQueueStrategy.h" +#include "EventLoop.h" + +namespace xwe = xbmc::wayland::events; + +/* Once xwe::Loop recieves some information we need to enqueue + * it to be dispatched on MessagePump. This is done by using + * a command pattern to wrap the incoming data in function objects + * and then pushing it to a queue. + * + * The reason for this is that these three functions may or may not + * be running in a separate thread depending on the dispatch + * strategy in place. */ +void xwe::Loop::OnEvent(XBMC_Event &e) +{ + m_eventQueue.PushAction(boost::bind(&IEventListener::OnEvent, + &m_queueListener, e)); +} + +void xwe::Loop::OnFocused() +{ + m_eventQueue.PushAction(boost::bind(&IEventListener::OnFocused, + &m_queueListener)); +} + +void xwe::Loop::OnUnfocused() +{ + m_eventQueue.PushAction(boost::bind(&IEventListener::OnUnfocused, + &m_queueListener)); +} + +xwe::Loop::Loop(IEventListener &queueListener, + IEventQueueStrategy &strategy) : + m_eventQueue(strategy), + m_queueListener(queueListener) +{ + m_stopWatch.StartZero(); +} + +namespace +{ +bool TimeoutInactive(const xwe::Loop::CallbackTracker &tracker) +{ + return tracker.callback.expired(); +} + +void SubtractTimeoutAndTrigger(xwe::Loop::CallbackTracker &tracker, + int time) +{ + int value = std::max(0, static_cast (tracker.remaining - time)); + if (value == 0) + { + tracker.remaining = time; + xbmc::ITimeoutManager::CallbackPtr callback (tracker.callback.lock()); + + (*callback) (); + } + else + tracker.remaining = value; +} + +bool ByRemaining(const xwe::Loop::CallbackTracker &a, + const xwe::Loop::CallbackTracker &b) +{ + return a.remaining < b.remaining; +} +} + +xwe::Loop::CallbackTracker::CallbackTracker(uint32_t time, + uint32_t initial, + const xbmc::ITimeoutManager::CallbackPtr &cb) : + time(time), + remaining(time > initial ? time : initial), + callback(cb) +{ +} + +void xwe::Loop::DispatchTimers() +{ + float elapsedMs = m_stopWatch.GetElapsedMilliseconds(); + m_stopWatch.Stop(); + /* We must subtract the elapsed time from each tracked timeout and + * trigger any remaining ones. If a timeout is triggered, then its + * remaining time will return to the original timeout value */ + std::for_each(m_callbackQueue.begin(), m_callbackQueue.end (), + boost::bind(SubtractTimeoutAndTrigger, + _1, + static_cast(elapsedMs))); + /* Timeout times may have changed so that the timeouts are no longer + * in order. Sort them so that they are. If they are unsorted, + * the ordering of two timeouts, one which was added just before + * the other which both reach a zero value at the same time, + * will be undefined. */ + std::sort(m_callbackQueue.begin(), m_callbackQueue.end(), + ByRemaining); + m_stopWatch.StartZero(); +} + +void xwe::Loop::Dispatch() +{ + /* Remove any timers which are no longer active */ + m_callbackQueue.erase (std::remove_if(m_callbackQueue.begin(), + m_callbackQueue.end(), + TimeoutInactive), + m_callbackQueue.end()); + + DispatchTimers(); + + /* Calculate the poll timeout based on any current + * timers on the main loop. */ + uint32_t minTimeout = 0; + for (std::vector::iterator it = m_callbackQueue.begin(); + it != m_callbackQueue.end(); + ++it) + { + if (minTimeout < it->remaining) + minTimeout = it->remaining; + } + + m_eventQueue.DispatchEventsFromMain(); +} + +xbmc::ITimeoutManager::CallbackPtr +xwe::Loop::RepeatAfterMs(const xbmc::ITimeoutManager::Callback &cb, + uint32_t initial, + uint32_t time) +{ + CallbackPtr ptr(new Callback(cb)); + + bool inserted = false; + + for (std::vector::iterator it = m_callbackQueue.begin(); + it != m_callbackQueue.end(); + ++it) + { + /* The appropriate place to insert is just before an existing + * timer which has a greater remaining time than ours */ + if (it->remaining > time) + { + m_callbackQueue.insert(it, CallbackTracker(time, initial, ptr)); + inserted = true; + break; + } + } + + /* Insert at the back */ + if (!inserted) + m_callbackQueue.push_back(CallbackTracker(time, initial, ptr)); + + return ptr; +} diff --git a/xbmc/windowing/wayland/EventLoop.h b/xbmc/windowing/wayland/EventLoop.h new file mode 100644 index 0000000000000..9664358527544 --- /dev/null +++ b/xbmc/windowing/wayland/EventLoop.h @@ -0,0 +1,92 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +#include "utils/Stopwatch.h" + +#include "EventListener.h" +#include "EventQueueStrategy.h" +#include "TimeoutManager.h" + +class IDllWaylandClient; + +struct wl_display; + +namespace xbmc +{ +namespace wayland +{ +namespace events +{ +class IEventQueueStrategy; + +/* Loop encapsulates the entire process of dispatching + * wayland events and timers that might be in place for duplicate + * processing. Calling its Dispatch() method will cause any pending + * timers and events to be dispatched. It implements ITimeoutManager + * and timeouts can be added directly to it */ +class Loop : + public xbmc::IEventListener, + public xbmc::ITimeoutManager +{ +public: + + Loop(xbmc::IEventListener &listener, + IEventQueueStrategy &strategy); + + void Dispatch(); + + struct CallbackTracker + { + typedef boost::weak_ptr CallbackObserver; + + CallbackTracker(uint32_t time, + uint32_t initial, + const CallbackPtr &callback); + + uint32_t time; + uint32_t remaining; + CallbackObserver callback; + }; + +private: + + CallbackPtr RepeatAfterMs(const Callback &callback, + uint32_t initial, + uint32_t timeout); + void DispatchTimers(); + + void OnEvent(XBMC_Event &); + void OnFocused(); + void OnUnfocused(); + + std::vector m_callbackQueue; + CStopWatch m_stopWatch; + + IEventQueueStrategy &m_eventQueue; + xbmc::IEventListener &m_queueListener; +}; +} +} +} diff --git a/xbmc/windowing/wayland/EventQueueStrategy.h b/xbmc/windowing/wayland/EventQueueStrategy.h new file mode 100644 index 0000000000000..c98b3536b185c --- /dev/null +++ b/xbmc/windowing/wayland/EventQueueStrategy.h @@ -0,0 +1,45 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +namespace xbmc +{ +namespace wayland +{ +namespace events +{ +class IEventQueueStrategy : + boost::noncopyable +{ +public: + + virtual ~IEventQueueStrategy() {} + + typedef boost::function Action; + + virtual void PushAction(const Action &event) = 0; + virtual void DispatchEventsFromMain() = 0; +}; +} +} +} diff --git a/xbmc/windowing/wayland/InputFactory.cpp b/xbmc/windowing/wayland/InputFactory.cpp new file mode 100644 index 0000000000000..4d9988c176532 --- /dev/null +++ b/xbmc/windowing/wayland/InputFactory.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include "EventListener.h" +#include "Keyboard.h" +#include "Pointer.h" +#include "Seat.h" +#include "TimeoutManager.h" +#include "InputFactory.h" + +namespace xw = xbmc::wayland; + +xbmc::InputFactory::InputFactory(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + struct wl_seat *seat, + IEventListener &dispatch, + ITimeoutManager &timeouts) : + m_clientLibrary(clientLibrary), + m_xkbCommonLibrary(xkbCommonLibrary), + m_pointerProcessor(dispatch, *this), + m_keyboardProcessor(dispatch, timeouts), + m_seat(new xw::Seat(clientLibrary, seat, *this)) +{ +} + +void xbmc::InputFactory::SetXBMCSurface(struct wl_surface *s) +{ + m_keyboardProcessor.SetXBMCSurface(s); +} + +void xbmc::InputFactory::SetCursor(uint32_t serial, + struct wl_surface *surface, + double surfaceX, + double surfaceY) +{ + m_pointer->SetCursor(serial, surface, surfaceX, surfaceY); +} + +bool xbmc::InputFactory::InsertPointer(struct wl_pointer *p) +{ + if (m_pointer.get()) + return false; + + m_pointer.reset(new xw::Pointer(m_clientLibrary, + p, + m_pointerProcessor)); + return true; +} + +bool xbmc::InputFactory::InsertKeyboard(struct wl_keyboard *k) +{ + if (m_keyboard.get()) + return false; + + m_keyboard.reset(new xw::Keyboard(m_clientLibrary, + m_xkbCommonLibrary, + k, + m_keyboardProcessor)); + return true; +} + +void xbmc::InputFactory::RemovePointer() +{ + m_pointer.reset(); +} + +void xbmc::InputFactory::RemoveKeyboard() +{ + m_keyboard.reset(); +} diff --git a/xbmc/windowing/wayland/InputFactory.h b/xbmc/windowing/wayland/InputFactory.h new file mode 100644 index 0000000000000..3f6d1746477d4 --- /dev/null +++ b/xbmc/windowing/wayland/InputFactory.h @@ -0,0 +1,82 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "CursorManager.h" +#include "Seat.h" +#include "Pointer.h" +#include "PointerProcessor.h" +#include "Keyboard.h" +#include "KeyboardProcessor.h" + +class IDllWaylandClient; +class IDllXKBCommon; + +struct wl_keyboard; +struct wl_pointer; +struct wl_seat; +struct wl_surface; + +namespace xbmc +{ +/* InputFactory is effectively just a manager class that encapsulates + * all input related information and ties together a wayland seat with + * the rest of the XBMC input handling subsystem. It is an internal + * class just for tying together these two ends. */ +class InputFactory : + public wayland::IInputReceiver, + public ICursorManager +{ +public: + + InputFactory(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + struct wl_seat *seat, + IEventListener &dispatch, + ITimeoutManager &timeouts); + + void SetXBMCSurface(struct wl_surface *s); + +private: + + void SetCursor(uint32_t serial, + struct wl_surface *surface, + double surfaceX, + double surfaceY); + + bool InsertPointer(struct wl_pointer *); + bool InsertKeyboard(struct wl_keyboard *); + + void RemovePointer(); + void RemoveKeyboard(); + + IDllWaylandClient &m_clientLibrary; + IDllXKBCommon &m_xkbCommonLibrary; + + PointerProcessor m_pointerProcessor; + KeyboardProcessor m_keyboardProcessor; + + boost::scoped_ptr m_seat; + boost::scoped_ptr m_pointer; + boost::scoped_ptr m_keyboard; +}; +} diff --git a/xbmc/windowing/wayland/Keyboard.cpp b/xbmc/windowing/wayland/Keyboard.cpp new file mode 100644 index 0000000000000..1321c67a3f793 --- /dev/null +++ b/xbmc/windowing/wayland/Keyboard.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include +#include +#include + +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/DllXKBCommon.h" +#include "windowing/WaylandProtocol.h" +#include "input/linux/XKBCommonKeymap.h" +#include "Keyboard.h" + +namespace xw = xbmc::wayland; + +const struct wl_keyboard_listener xw::Keyboard::m_listener = +{ + Keyboard::HandleKeymapCallback, + Keyboard::HandleEnterCallback, + Keyboard::HandleLeaveCallback, + Keyboard::HandleKeyCallback, + Keyboard::HandleModifiersCallback +}; + +namespace +{ +void DestroyXKBCommonContext(struct xkb_context *context, + IDllXKBCommon &xkbCommonLibrary) +{ + xkbCommonLibrary.xkb_context_unref(context); +} +} + +xw::Keyboard::Keyboard(IDllWaylandClient &clientLibrary, + IDllXKBCommon &xkbCommonLibrary, + struct wl_keyboard *keyboard, + IKeyboardReceiver &receiver) : + m_clientLibrary(clientLibrary), + m_xkbCommonLibrary(xkbCommonLibrary), + m_xkbCommonContext(CXKBKeymap::CreateXKBContext(m_xkbCommonLibrary), + boost::bind(DestroyXKBCommonContext, + _1, + boost::ref(m_xkbCommonLibrary))), + m_keyboard(keyboard), + m_reciever(receiver) +{ + protocol::AddListenerOnWaylandObject(m_clientLibrary, + m_keyboard, + &m_listener, + this); +} + +xw::Keyboard::~Keyboard() +{ + protocol::DestroyWaylandObject(m_clientLibrary, + m_keyboard); +} + +void xw::Keyboard::HandleKeymapCallback(void *data, + struct wl_keyboard *keyboard, + uint32_t format, + int fd, + uint32_t size) +{ + static_cast (data)->HandleKeymap(format, + fd, + size); +} + +void xw::Keyboard::HandleEnterCallback(void *data, + struct wl_keyboard *keyboard, + uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys) +{ + static_cast(data)->HandleEnter(serial, + surface, + keys); +} + +void xw::Keyboard::HandleLeaveCallback(void *data, + struct wl_keyboard *keyboard, + uint32_t serial, + struct wl_surface *surface) +{ + static_cast(data)->HandleLeave(serial, + surface); +} + +void xw::Keyboard::HandleKeyCallback(void *data, + struct wl_keyboard *keyboard, + uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state) +{ + static_cast(data)->HandleKey(serial, + time, + key, + state); +} + +void xw::Keyboard::HandleModifiersCallback(void *data, + struct wl_keyboard *keyboard, + uint32_t serial, + uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group) +{ + static_cast(data)->HandleModifiers(serial, + mods_depressed, + mods_latched, + mods_locked, + group); +} + +/* Creates a new internal keymap representation for a serialized + * keymap as represented in shared memory as referred to by fd. + * + * Since the fd is sent to us via sendmsg(), the currently running + * process has ownership over it. As such, it MUST close the file + * descriptor after it has decided what to do with it in order to + * avoid a leak. + */ +void xw::Keyboard::HandleKeymap(uint32_t format, + int fd, + uint32_t size) +{ + /* The file descriptor must always be closed */ + BOOST_SCOPE_EXIT((fd)) + { + close(fd); + } BOOST_SCOPE_EXIT_END + + /* We don't understand anything other than xkbv1. If we get some + * other keyboard, then we can't process keyboard events reliably + * and that's a runtime error. */ + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) + throw std::runtime_error("Server gave us a keymap we don't understand"); + + bool successfullyCreatedKeyboard = false; + + /* Either throws or returns a valid xkb_keymap * */ + struct xkb_keymap *keymap = + CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(m_xkbCommonLibrary, + m_xkbCommonContext.get(), + fd, + size); + + BOOST_SCOPE_EXIT((&m_xkbCommonLibrary)(&successfullyCreatedKeyboard)(keymap)) + { + if (!successfullyCreatedKeyboard) + m_xkbCommonLibrary.xkb_keymap_unref(keymap); + } BOOST_SCOPE_EXIT_END + + m_keymap.reset(new CXKBKeymap(m_xkbCommonLibrary, + keymap)); + + successfullyCreatedKeyboard = true; + + m_reciever.UpdateKeymap(m_keymap.get()); +} + +void xw::Keyboard::HandleEnter(uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys) +{ + m_reciever.Enter(serial, surface, keys); +} + +void xw::Keyboard::HandleLeave(uint32_t serial, + struct wl_surface *surface) +{ + m_reciever.Leave(serial, surface); +} + +void xw::Keyboard::HandleKey(uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state) +{ + m_reciever.Key(serial, + time, + key, + static_cast(state)); +} + +void xw::Keyboard::HandleModifiers(uint32_t serial, + uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group) +{ + m_reciever.Modifier(serial, + mods_depressed, + mods_latched, + mods_locked, + group); +} diff --git a/xbmc/windowing/wayland/Keyboard.h b/xbmc/windowing/wayland/Keyboard.h new file mode 100644 index 0000000000000..44cb59fafa4db --- /dev/null +++ b/xbmc/windowing/wayland/Keyboard.h @@ -0,0 +1,156 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include + +#include "input/linux/Keymap.h" + +class IDllWaylandClient; +class IDllXKBCommon; + +struct xkb_context; + +namespace xbmc +{ +namespace wayland +{ +class IKeyboardReceiver +{ +public: + + virtual ~IKeyboardReceiver() {} + + virtual void UpdateKeymap(ILinuxKeymap *) = 0; + virtual void Enter(uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys) = 0; + virtual void Leave(uint32_t serial, + struct wl_surface *surface) = 0; + virtual void Key(uint32_t serial, + uint32_t time, + uint32_t key, + enum wl_keyboard_key_state state) = 0; + virtual void Modifier(uint32_t serial, + uint32_t depressed, + uint32_t latched, + uint32_t locked, + uint32_t group) = 0; +}; + +/* Wrapper class for a keyboard object. Generally there is one keyboard + * per seat. + * + * Keyboard events are translated into a more readable form and + * forwarded on to the injected IKeyboardReceiver for further + * processing. + * + * Many of these events require some shared agreement between the + * compositor and the client as to the keymap in use. A file descriptor + * for a shared memory region to a serialized keymap parsable + * with libxkbcommon is provided in HandleKeymap and to the + * registered IKeyboardReceiever through UpdateKeymap. The delegate for + * that interface should ascertain the intended keymap before processing + * any other events. + */ +class Keyboard : + public boost::noncopyable +{ +public: + + Keyboard(IDllWaylandClient &, + IDllXKBCommon &, + struct wl_keyboard *, + IKeyboardReceiver &); + ~Keyboard(); + + struct wl_keyboard * GetWlKeyboard(); + + static void HandleKeymapCallback(void *, + struct wl_keyboard *, + uint32_t, + int, + uint32_t); + static void HandleEnterCallback(void *, + struct wl_keyboard *, + uint32_t, + struct wl_surface *, + struct wl_array *); + static void HandleLeaveCallback(void *, + struct wl_keyboard *, + uint32_t, + struct wl_surface *); + static void HandleKeyCallback(void *, + struct wl_keyboard *, + uint32_t, + uint32_t, + uint32_t, + uint32_t); + static void HandleModifiersCallback(void *, + struct wl_keyboard *, + uint32_t, + uint32_t, + uint32_t, + uint32_t, + uint32_t); + +private: + + void HandleKeymap(uint32_t format, + int fd, + uint32_t size); + void HandleEnter(uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys); + void HandleLeave(uint32_t serial, + struct wl_surface *surface); + void HandleKey(uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state); + void HandleModifiers(uint32_t serial, + uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group); + + static const struct wl_keyboard_listener m_listener; + + IDllWaylandClient &m_clientLibrary; + IDllXKBCommon &m_xkbCommonLibrary; + + /* boost::scoped_ptr does not permit custom deleters + * and std::auto_ptr is deprecated, so we are using + * boost::shared_ptr instead */ + boost::shared_ptr m_xkbCommonContext; + struct wl_keyboard *m_keyboard; + IKeyboardReceiver &m_reciever; + + /* Keyboard owns the keymap object, but it might inject observing + * references elsewhere in order to assist those objects in their + * processing */ + boost::scoped_ptr m_keymap; +}; +} +} diff --git a/xbmc/windowing/wayland/KeyboardProcessor.cpp b/xbmc/windowing/wayland/KeyboardProcessor.cpp new file mode 100644 index 0000000000000..0f01b2efb498e --- /dev/null +++ b/xbmc/windowing/wayland/KeyboardProcessor.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "utils/log.h" + +#include "EventListener.h" +#include "Keyboard.h" +#include "KeyboardProcessor.h" +#include "TimeoutManager.h" + +#include "input/linux/Keymap.h" + + +xbmc::KeyboardProcessor::KeyboardProcessor(IEventListener &listener, + ITimeoutManager &timeouts) : + m_listener(listener), + m_timeouts(timeouts), + m_xbmcWindow(NULL), + m_repeatSym(0), + m_context(NULL) +{ +} + +xbmc::KeyboardProcessor::~KeyboardProcessor() +{ +} + +void +xbmc::KeyboardProcessor::SetXBMCSurface(struct wl_surface *s) +{ + m_xbmcWindow = s; +} + +/* Takes an observing reference to an ILinuxKeymap */ +void +xbmc::KeyboardProcessor::UpdateKeymap(ILinuxKeymap *keymap) +{ + m_keymap = keymap; +} + +void +xbmc::KeyboardProcessor::Enter(uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys) +{ + if (surface == m_xbmcWindow) + { + m_listener.OnFocused(); + } +} + +void +xbmc::KeyboardProcessor::Leave(uint32_t serial, + struct wl_surface *surface) +{ + if (surface == m_xbmcWindow) + { + m_listener.OnUnfocused(); + } +} + +void +xbmc::KeyboardProcessor::SendKeyToXBMC(uint32_t key, + uint32_t sym, + uint32_t eventType) +{ + if (!m_keymap) + throw std::logic_error("a keymap must be set before processing key events"); + + XBMC_Event event; + event.type = eventType; + event.key.keysym.scancode = key; + event.key.keysym.sym = static_cast(sym); + event.key.keysym.unicode = static_cast(sym); + event.key.keysym.mod = + static_cast(m_keymap->ActiveXBMCModifiers()); + event.key.state = 0; + event.key.type = event.type; + event.key.which = '0'; + + m_listener.OnEvent(event); +} + +void +xbmc::KeyboardProcessor::RepeatCallback(uint32_t key, + uint32_t sym) +{ + /* Release and press the key again */ + SendKeyToXBMC(key, sym, XBMC_KEYUP); + SendKeyToXBMC(key, sym, XBMC_KEYDOWN); +} + +/* If this function is called before a keymap is set, then that + * is a precondition violation and a logic_error results */ +void +xbmc::KeyboardProcessor::Key(uint32_t serial, + uint32_t time, + uint32_t key, + enum wl_keyboard_key_state state) +{ + if (!m_keymap) + throw std::logic_error("a keymap must be set before processing key events"); + + uint32_t sym = XKB_KEY_NoSymbol; + + /* If we're unable to process a single key, then catch the error + * and report it, but don't allow it to be fatal */ + try + { + sym = m_keymap->XBMCKeysymForKeycode(key); + } + catch (const std::runtime_error &err) + { + CLog::Log(LOGERROR, "%s: Failed to process keycode %i: %s", + __FUNCTION__, key, err.what()); + return; + } + + uint32_t keyEventType = 0; + + switch (state) + { + case WL_KEYBOARD_KEY_STATE_PRESSED: + keyEventType = XBMC_KEYDOWN; + break; + case WL_KEYBOARD_KEY_STATE_RELEASED: + keyEventType = XBMC_KEYUP; + break; + default: + CLog::Log(LOGERROR, "%s: Unrecognized key state", __FUNCTION__); + return; + } + + /* Key-repeat is handled on the client side so we need to add a new + * timeout here to repeat this symbol if it is still being held down + */ + if (keyEventType == XBMC_KEYDOWN) + { + m_repeatCallback = + m_timeouts.RepeatAfterMs(boost::bind ( + &KeyboardProcessor::RepeatCallback, + this, + key, + sym), + 1000, + 250); + m_repeatSym = sym; + } + else if (keyEventType == XBMC_KEYUP && + sym == m_repeatSym) + m_repeatCallback.reset(); + + SendKeyToXBMC(key, sym, keyEventType); +} + +/* We MUST update the keymap mask whenever we receive a new modifier + * event */ +void +xbmc::KeyboardProcessor::Modifier(uint32_t serial, + uint32_t depressed, + uint32_t latched, + uint32_t locked, + uint32_t group) +{ + if (!m_keymap) + throw std::logic_error("a keymap must be set before processing key events"); + + m_keymap->UpdateMask(depressed, latched, locked, group); +} diff --git a/xbmc/windowing/wayland/KeyboardProcessor.h b/xbmc/windowing/wayland/KeyboardProcessor.h new file mode 100644 index 0000000000000..3a6af534456ca --- /dev/null +++ b/xbmc/windowing/wayland/KeyboardProcessor.h @@ -0,0 +1,98 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include "input/linux/Keymap.h" +#include "Keyboard.h" +#include "TimeoutManager.h" + +class IDllXKBCommon; + +struct wl_array; +struct wl_surface; +struct xkb_context; +enum wl_keyboard_key_state; + +namespace xbmc +{ +class IEventListener; + +/* KeyboardProcessor implements IKeyboardReceiver and transforms + * keyboard events into XBMC events for further processing. + * + * It needs to know whether or not a surface is in focus, so as soon + * as a surface is available, SetXBMCSurface should be called. + * + * KeyboardProcessor also performs key-repeat and registers a callback + * function to repeat the currently depressed key if it has not been + * released within a certain period. As such it depends on + * ITimeoutManager */ +class KeyboardProcessor : + public wayland::IKeyboardReceiver +{ +public: + + KeyboardProcessor(IEventListener &listener, + ITimeoutManager &timeouts); + ~KeyboardProcessor(); + + void SetXBMCSurface(struct wl_surface *xbmcWindow); + +private: + + void UpdateKeymap(ILinuxKeymap *); + void Enter(uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys); + void Leave(uint32_t serial, + struct wl_surface *surface); + void Key(uint32_t serial, + uint32_t time, + uint32_t key, + enum wl_keyboard_key_state state); + void Modifier(uint32_t serial, + uint32_t depressed, + uint32_t latched, + uint32_t locked, + uint32_t group); + + void SendKeyToXBMC(uint32_t key, + uint32_t sym, + uint32_t type); + void RepeatCallback(uint32_t key, + uint32_t sym); + + IEventListener &m_listener; + ITimeoutManager &m_timeouts; + struct wl_surface *m_xbmcWindow; + + ITimeoutManager::CallbackPtr m_repeatCallback; + uint32_t m_repeatSym; + + struct xkb_context *m_context; + + /* KeyboardProcessor has an observing reference to the keymap and + * does parts of its processing by delegating to the keymap the job + * of looking up generic keysyms for keycodes */ + ILinuxKeymap *m_keymap; +}; +} diff --git a/xbmc/windowing/wayland/Pointer.cpp b/xbmc/windowing/wayland/Pointer.cpp new file mode 100644 index 0000000000000..b66e4a9a7ba64 --- /dev/null +++ b/xbmc/windowing/wayland/Pointer.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Pointer.h" + +namespace xw = xbmc::wayland; + +const struct wl_pointer_listener xw::Pointer::m_listener = +{ + Pointer::HandleEnterCallback, + Pointer::HandleLeaveCallback, + Pointer::HandleMotionCallback, + Pointer::HandleButtonCallback, + Pointer::HandleAxisCallback +}; + +xw::Pointer::Pointer(IDllWaylandClient &clientLibrary, + struct wl_pointer *pointer, + IPointerReceiver &receiver) : + m_clientLibrary(clientLibrary), + m_pointer(pointer), + m_receiver(receiver) +{ + protocol::AddListenerOnWaylandObject(m_clientLibrary, + pointer, + &m_listener, + this); +} + +xw::Pointer::~Pointer() +{ + protocol::DestroyWaylandObject(m_clientLibrary, + m_pointer); +} + +void xw::Pointer::SetCursor(uint32_t serial, + struct wl_surface *surface, + int32_t hotspot_x, + int32_t hotspot_y) +{ + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_pointer, + WL_POINTER_SET_CURSOR, + serial, + surface, + hotspot_x, + hotspot_y); +} + +void xw::Pointer::HandleEnterCallback(void *data, + struct wl_pointer *pointer, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t x, + wl_fixed_t y) +{ + static_cast(data)->HandleEnter(serial, + surface, + x, + y); +} + +void xw::Pointer::HandleLeaveCallback(void *data, + struct wl_pointer *pointer, + uint32_t serial, + struct wl_surface *surface) +{ + static_cast(data)->HandleLeave(serial, surface); +} + +void xw::Pointer::HandleMotionCallback(void *data, + struct wl_pointer *pointer, + uint32_t time, + wl_fixed_t x, + wl_fixed_t y) +{ + static_cast(data)->HandleMotion(time, + x, + y); +} + +void xw::Pointer::HandleButtonCallback(void *data, + struct wl_pointer * pointer, + uint32_t serial, + uint32_t time, + uint32_t button, + uint32_t state) +{ + static_cast(data)->HandleButton(serial, + time, + button, + state); +} + +void xw::Pointer::HandleAxisCallback(void *data, + struct wl_pointer *pointer, + uint32_t time, + uint32_t axis, + wl_fixed_t value) +{ + static_cast(data)->HandleAxis(time, + axis, + value); +} + +void xw::Pointer::HandleEnter(uint32_t serial, + struct wl_surface *surface, + wl_fixed_t surfaceXFixed, + wl_fixed_t surfaceYFixed) +{ + m_receiver.Enter(surface, + wl_fixed_to_double(surfaceXFixed), + wl_fixed_to_double(surfaceYFixed)); +} + +void xw::Pointer::HandleLeave(uint32_t serial, + struct wl_surface *surface) +{ +} + +void xw::Pointer::HandleMotion(uint32_t time, + wl_fixed_t surfaceXFixed, + wl_fixed_t surfaceYFixed) +{ + m_receiver.Motion(time, + wl_fixed_to_double(surfaceXFixed), + wl_fixed_to_double(surfaceYFixed)); +} + +void xw::Pointer::HandleButton(uint32_t serial, + uint32_t time, + uint32_t button, + uint32_t state) +{ + m_receiver.Button(serial, + time, + button, + static_cast(state)); +} + +void xw::Pointer::HandleAxis(uint32_t time, + uint32_t axis, + wl_fixed_t value) +{ + m_receiver.Axis(time, + axis, + wl_fixed_to_double(value)); +} diff --git a/xbmc/windowing/wayland/Pointer.h b/xbmc/windowing/wayland/Pointer.h new file mode 100644 index 0000000000000..b617d5495dac8 --- /dev/null +++ b/xbmc/windowing/wayland/Pointer.h @@ -0,0 +1,130 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +class IDllWaylandClient; + +namespace xbmc +{ +namespace wayland +{ +class IPointerReceiver +{ +public: + + virtual ~IPointerReceiver() {} + virtual void Motion(uint32_t time, + const float &x, + const float &y) = 0; + virtual void Button(uint32_t serial, + uint32_t time, + uint32_t button, + enum wl_pointer_button_state state) = 0; + virtual void Axis(uint32_t time, + uint32_t axis, + float value) = 0; + virtual void Enter(struct wl_surface *surface, + double surfaceX, + double surfaceY) = 0; +}; + +/* Wrapper class for a pointer object. Generally there is one pointer + * per seat. + * + * Events are forwarded from the internal proxy to an IPointerReceiver + * for further processing. The responsibility of this class is only + * to receive the events and represent them in a sensible way */ +class Pointer +{ +public: + + Pointer(IDllWaylandClient &, + struct wl_pointer *, + IPointerReceiver &); + ~Pointer(); + + struct wl_pointer * GetWlPointer(); + + /* This method changes the cursor to have the contents of + * an arbitrary surface on the server side. It can also hide + * the cursor if NULL is passed as "surface" */ + void SetCursor(uint32_t serial, + struct wl_surface *surface, + int32_t hotspot_x, + int32_t hotspot_y); + + static void HandleEnterCallback(void *, + struct wl_pointer *, + uint32_t, + struct wl_surface *, + wl_fixed_t, + wl_fixed_t); + static void HandleLeaveCallback(void *, + struct wl_pointer *, + uint32_t, + struct wl_surface *); + static void HandleMotionCallback(void *, + struct wl_pointer *, + uint32_t, + wl_fixed_t, + wl_fixed_t); + static void HandleButtonCallback(void *, + struct wl_pointer *, + uint32_t, + uint32_t, + uint32_t, + uint32_t); + static void HandleAxisCallback(void *, + struct wl_pointer *, + uint32_t, + uint32_t, + wl_fixed_t); + +private: + + void HandleEnter(uint32_t serial, + struct wl_surface *surface, + wl_fixed_t surfaceXFixed, + wl_fixed_t surfaceYFixed); + void HandleLeave(uint32_t serial, + struct wl_surface *surface); + void HandleMotion(uint32_t time, + wl_fixed_t surfaceXFixed, + wl_fixed_t surfaceYFixed); + void HandleButton(uint32_t serial, + uint32_t time, + uint32_t button, + uint32_t state); + void HandleAxis(uint32_t time, + uint32_t axis, + wl_fixed_t value); + + static const struct wl_pointer_listener m_listener; + + IDllWaylandClient &m_clientLibrary; + struct wl_pointer *m_pointer; + IPointerReceiver &m_receiver; +}; +} +} diff --git a/xbmc/windowing/wayland/PointerProcessor.cpp b/xbmc/windowing/wayland/PointerProcessor.cpp new file mode 100644 index 0000000000000..20abab6d4f763 --- /dev/null +++ b/xbmc/windowing/wayland/PointerProcessor.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/DllXKBCommon.h" + +#include "CursorManager.h" +#include "EventListener.h" +#include "Pointer.h" +#include "PointerProcessor.h" +#include "Util.h" + +xbmc::PointerProcessor::PointerProcessor(IEventListener &listener, + ICursorManager &manager) : + m_listener(listener), + m_cursorManager(manager) +{ +} + +void xbmc::PointerProcessor::Motion(uint32_t time, + const float &x, + const float &y) +{ + XBMC_Event event; + + event.type = XBMC_MOUSEMOTION; + event.motion.xrel = ::round(x); + event.motion.yrel = ::round(y); + event.motion.state = 0; + event.motion.type = XBMC_MOUSEMOTION; + event.motion.which = 0; + event.motion.x = event.motion.xrel; + event.motion.y = event.motion.yrel; + + m_lastPointerX = x; + m_lastPointerY = y; + + m_listener.OnEvent(event); +} + +void xbmc::PointerProcessor::Button(uint32_t serial, + uint32_t time, + uint32_t button, + enum wl_pointer_button_state state) +{ + static const struct ButtonTable + { + unsigned int WaylandButton; + unsigned int XBMCButton; + } buttonTable[] = + { + { WaylandLeftButton, 1 }, + { WaylandMiddleButton, 2 }, + { WaylandRightButton, 3 } + }; + + size_t buttonTableSize = ARRAY_SIZE(buttonTable); + + /* Find the xbmc button number that corresponds to the evdev + * button that we just received. There may be some buttons we don't + * recognize so just ignore them */ + unsigned int xbmcButton = 0; + + for (size_t i = 0; i < buttonTableSize; ++i) + if (buttonTable[i].WaylandButton == button) + xbmcButton = buttonTable[i].XBMCButton; + + if (!xbmcButton) + return; + + /* Keep track of currently pressed buttons, we need that for + * motion events */ + if (state & WL_POINTER_BUTTON_STATE_PRESSED) + m_currentlyPressedButton |= 1 << button; + else if (state & WL_POINTER_BUTTON_STATE_RELEASED) + m_currentlyPressedButton &= ~(1 << button); + + XBMC_Event event; + + event.type = state & WL_POINTER_BUTTON_STATE_PRESSED ? + XBMC_MOUSEBUTTONDOWN : XBMC_MOUSEBUTTONUP; + event.button.button = xbmcButton; + event.button.state = 0; + event.button.type = event.type; + event.button.which = 0; + event.button.x = ::round(m_lastPointerX); + event.button.y = ::round(m_lastPointerY); + + m_listener.OnEvent(event); +} + +void xbmc::PointerProcessor::Axis(uint32_t time, + uint32_t axis, + float value) +{ + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) + { + /* Negative is up */ + bool direction = value < 0.0f; + int button = direction ? WheelUpButton : + WheelDownButton; + + /* For axis events we only care about the vector direction + * and not the scalar magnitude. Every axis event callback + * generates one scroll button event for XBMC */ + XBMC_Event event; + + event.type = XBMC_MOUSEBUTTONDOWN; + event.button.button = button; + event.button.state = 0; + event.button.type = XBMC_MOUSEBUTTONDOWN; + event.button.which = 0; + event.button.x = ::round(m_lastPointerX); + event.button.y = ::round(m_lastPointerY); + + m_listener.OnEvent(event); + + /* We must also send a button up on the same + * wheel "button" */ + event.type = XBMC_MOUSEBUTTONUP; + event.button.type = XBMC_MOUSEBUTTONUP; + + m_listener.OnEvent(event); + } +} + +void +xbmc::PointerProcessor::Enter(struct wl_surface *surface, + double surfaceX, + double surfaceY) +{ + m_cursorManager.SetCursor(0, NULL, 0, 0); +} diff --git a/xbmc/windowing/wayland/PointerProcessor.h b/xbmc/windowing/wayland/PointerProcessor.h new file mode 100644 index 0000000000000..8844ed0d00d9a --- /dev/null +++ b/xbmc/windowing/wayland/PointerProcessor.h @@ -0,0 +1,76 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include "Pointer.h" + +struct wl_surface; + +namespace xbmc +{ +class IEventListener; +class ICursorManager; + +/* PointerProcessor implements IPointerReceiver and transforms input + * wayland mouse event callbacks into XBMC events. It also handles + * changing the cursor image on surface entry */ +class PointerProcessor : + public wayland::IPointerReceiver +{ +public: + + PointerProcessor(IEventListener &, + ICursorManager &); + +private: + + void Motion(uint32_t time, + const float &x, + const float &y); + void Button(uint32_t serial, + uint32_t time, + uint32_t button, + enum wl_pointer_button_state state); + void Axis(uint32_t time, + uint32_t axis, + float value); + void Enter(struct wl_surface *surface, + double surfaceX, + double surfaceY); + + IEventListener &m_listener; + ICursorManager &m_cursorManager; + + uint32_t m_currentlyPressedButton; + float m_lastPointerX; + float m_lastPointerY; + + /* There is no defined export for these buttons - + * wayland appears to just be using the evdev codes + * directly */ + static const unsigned int WaylandLeftButton = 272; + static const unsigned int WaylandRightButton = 273; + static const unsigned int WaylandMiddleButton = 274; + + static const unsigned int WheelUpButton = 4; + static const unsigned int WheelDownButton = 5; + +}; +} diff --git a/xbmc/windowing/wayland/PollThread.cpp b/xbmc/windowing/wayland/PollThread.cpp new file mode 100644 index 0000000000000..70732fc950004 --- /dev/null +++ b/xbmc/windowing/wayland/PollThread.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include +#include +#include + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include + +#include "utils/log.h" + +#include "PollThread.h" + +namespace xwe = xbmc::wayland::events; + +xwe::PollThread::PollThread(const Dispatch &dispatch, + const Dispatch &beforePoll, + int fd) : + CThread("wayland-event-thread"), + m_dispatch(dispatch), + m_beforePoll(beforePoll), + m_fd(fd) +{ + /* Create wakeup pipe. We will poll on the read end of this. If + * there are any events, it means its time to shut down */ + if (pipe2(m_wakeupPipe, O_CLOEXEC) == -1) + { + std::stringstream ss; + ss << strerror(errno); + throw std::runtime_error(ss.str()); + } + + /* Create poll thread */ + Create(); +} + +xwe::PollThread::~PollThread() +{ + /* Send a message to the reader thread that its time to shut down */ + if (write(m_wakeupPipe[1], (const void *) "q", 1) == -1) + CLog::Log(LOGERROR, "%s: Failed to write to shutdown wakeup pipe. " + "Application may hang. Reason was: %s", + __FUNCTION__, strerror(errno)); + + /* Close the write end, as we no longer need it */ + if (close(m_wakeupPipe[1]) == -1) + CLog::Log(LOGERROR, "%s: Failed to close shutdown pipe write end. " + "Leak may occurr. Reason was: %s", + __FUNCTION__, strerror(errno)); + + /* The destructor for CThread will cause it to join */ +} + +namespace +{ +bool Ready(int revents) +{ + if (revents & (POLLHUP | POLLERR)) + CLog::Log(LOGERROR, "%s: Error on fd. Reason was: %s", + __FUNCTION__, strerror(errno)); + + return revents & POLLIN; +} +} + +void +xwe::PollThread::Process() +{ + static const unsigned int MonitoredFdIndex = 0; + static const unsigned int ShutdownFdIndex = 1; + + while (1) + { + struct pollfd pfd[2] = + { + { m_fd, POLLIN | POLLHUP | POLLERR, 0 }, + { m_wakeupPipe[0], POLLIN | POLLHUP | POLLERR, 0 } + }; + + m_beforePoll(); + + /* Sleep forever until something happens */ + if (poll(pfd, 2, -1) == -1) + CLog::Log(LOGERROR, "%s: Poll failed. Reason was: %s", + __FUNCTION__, strerror(errno)); + + /* Check the shutdown pipe first as we might need to + * shutdown */ + if (Ready(pfd[ShutdownFdIndex].revents)) + { + if (close(m_wakeupPipe[0]) == -1) + CLog::Log(LOGERROR, "%s: Failed to close shutdown pipe read end. " + "Leak may occurr. Reason was: %s", + __FUNCTION__, strerror(errno)); + return; + } + else if (Ready(pfd[MonitoredFdIndex].revents)) + m_dispatch(); + } +} diff --git a/xbmc/windowing/wayland/PollThread.h b/xbmc/windowing/wayland/PollThread.h new file mode 100644 index 0000000000000..07ca2d2bc1448 --- /dev/null +++ b/xbmc/windowing/wayland/PollThread.h @@ -0,0 +1,65 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +#include "threads/Thread.h" + +namespace xbmc +{ +namespace wayland +{ +namespace events +{ +/* This is effectively a "reader" worker thread. It has two + * injected extension points - dispatch and beforePoll and takes + * a file descriptor related to those two extension points for polling. + * + * Before polling occurrs, beforePoll() is called and then this thread + * will poll on two file descriptors - the provided one and an internal + * one to manage thread joins. If data is ready on the file descriptor, + * then dispatch() will be called. + */ +class PollThread : + public CThread +{ +public: + + typedef boost::function Dispatch; + + PollThread(const Dispatch &dispatch, + const Dispatch &beforePoll, + int fd); + ~PollThread(); + +private: + + void Process(); + + Dispatch m_dispatch; + Dispatch m_beforePoll; + int m_fd; + int m_wakeupPipe[2]; +}; +} +} +} diff --git a/xbmc/windowing/wayland/Seat.cpp b/xbmc/windowing/wayland/Seat.cpp new file mode 100644 index 0000000000000..fbd11c47abeec --- /dev/null +++ b/xbmc/windowing/wayland/Seat.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#include + +#include "windowing/DllWaylandClient.h" +#include "windowing/WaylandProtocol.h" +#include "Seat.h" + +namespace xw = xbmc::wayland; + +/* We only support version 1 of this interface, the + * other struct members are impliedly set to NULL */ +const struct wl_seat_listener xw::Seat::m_listener = +{ + Seat::HandleCapabilitiesCallback +}; + +xw::Seat::Seat(IDllWaylandClient &clientLibrary, + struct wl_seat *seat, + IInputReceiver &reciever) : + m_clientLibrary(clientLibrary), + m_seat(seat), + m_input(reciever), + m_currentCapabilities(static_cast(0)) +{ + protocol::AddListenerOnWaylandObject(m_clientLibrary, + m_seat, + &m_listener, + reinterpret_cast(this)); +} + +xw::Seat::~Seat() +{ + protocol::DestroyWaylandObject(m_clientLibrary, + m_seat); +} + +void xw::Seat::HandleCapabilitiesCallback(void *data, + struct wl_seat *seat, + uint32_t cap) +{ + enum wl_seat_capability capabilities = + static_cast(cap); + static_cast(data)->HandleCapabilities(capabilities); +} + +/* The capabilities callback is effectively like a mini-registry + * for all of the child objects of a Seat */ +void xw::Seat::HandleCapabilities(enum wl_seat_capability cap) +{ + enum wl_seat_capability newCaps = + static_cast(~m_currentCapabilities & cap); + enum wl_seat_capability lostCaps = + static_cast(m_currentCapabilities & ~cap); + + if (newCaps & WL_SEAT_CAPABILITY_POINTER) + { + struct wl_pointer *pointer = + protocol::CreateWaylandObject(m_clientLibrary, + m_seat, + m_clientLibrary.Get_wl_pointer_interface()); + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_seat, + WL_SEAT_GET_POINTER, + pointer); + m_input.InsertPointer(pointer); + } + + if (newCaps & WL_SEAT_CAPABILITY_KEYBOARD) + { + struct wl_keyboard *keyboard = + protocol::CreateWaylandObject(m_clientLibrary, + m_seat, + m_clientLibrary.Get_wl_keyboard_interface()); + protocol::CallMethodOnWaylandObject(m_clientLibrary, + m_seat, + WL_SEAT_GET_KEYBOARD, + keyboard); + m_input.InsertKeyboard(keyboard); + } + + if (lostCaps & WL_SEAT_CAPABILITY_POINTER) + m_input.RemovePointer(); + + if (lostCaps & WL_SEAT_CAPABILITY_KEYBOARD) + m_input.RemoveKeyboard(); + + m_currentCapabilities = cap; +} diff --git a/xbmc/windowing/wayland/Seat.h b/xbmc/windowing/wayland/Seat.h new file mode 100644 index 0000000000000..49ae3aad06a81 --- /dev/null +++ b/xbmc/windowing/wayland/Seat.h @@ -0,0 +1,74 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +class IDllWaylandClient; + +namespace xbmc +{ +namespace wayland +{ +class IInputReceiver +{ +public: + + virtual ~IInputReceiver() {} + + virtual bool InsertPointer(struct wl_pointer *pointer) = 0; + virtual bool InsertKeyboard(struct wl_keyboard *keyboard) = 0; + + virtual void RemovePointer() = 0; + virtual void RemoveKeyboard() = 0; +}; + +class Seat : + public boost::noncopyable +{ +public: + + Seat(IDllWaylandClient &, + struct wl_seat *, + IInputReceiver &); + ~Seat(); + + struct wl_seat * GetWlSeat(); + + static void HandleCapabilitiesCallback(void *, + struct wl_seat *, + uint32_t); + +private: + + static const struct wl_seat_listener m_listener; + + void HandleCapabilities(enum wl_seat_capability); + + IDllWaylandClient &m_clientLibrary; + struct wl_seat * m_seat; + IInputReceiver &m_input; + + enum wl_seat_capability m_currentCapabilities; +}; +} +} diff --git a/xbmc/windowing/wayland/TimeoutManager.h b/xbmc/windowing/wayland/TimeoutManager.h new file mode 100644 index 0000000000000..c1dea95f10de1 --- /dev/null +++ b/xbmc/windowing/wayland/TimeoutManager.h @@ -0,0 +1,45 @@ +#pragma once + +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include + +namespace xbmc +{ +/* ITimeoutManager defines an interface for arbitary classes + * to register full closures to be called initially on a timeout + * specified by initial and then subsequently on a timeout specified + * by timeout. The interface is more or less artificial and exists to + * break the dependency between keyboard processing code and + * actual system timers, whcih is useful for testing purposes */ +class ITimeoutManager +{ +public: + + typedef boost::function Callback; + typedef boost::shared_ptr CallbackPtr; + + virtual ~ITimeoutManager() {} + virtual CallbackPtr RepeatAfterMs (const Callback &callback, + uint32_t initial, + uint32_t timeout) = 0; +}; +} diff --git a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp new file mode 100644 index 0000000000000..c2bd327804f2c --- /dev/null +++ b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include +#include +#include + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "windowing/DllWaylandClient.h" +#include "utils/log.h" + +#include "Wayland11EventQueueStrategy.h" + +namespace xwe = xbmc::wayland::events; +namespace xw11 = xbmc::wayland::version_11; + +/* It is very important that these functions occurr in the order. + * that they are written below. Deadlocks might occurr otherwise. + * + * The first function dispatches any pending events that have been + * determined from prior reads of the event queue without *also* + * reading the event queue. + * + * The second function function reads the input buffer and dispatches + * any events that occurred, but only after the reading thread goes + * to sleep waiting for new data to arrive on the pipe. + * + * The output buffer will be flushed periodically (on the render loop, + * which never sleeps) and will flush any pending requests after + * eglSwapBuffers that may have happened just before this thread starts + * polling. + * + * If the functions are not called in this order, you might run into + * a situation where pending-dispatch events might have generated a + * write to the event queue in order to keep us awake (frame events + * are a particular culprit here), or where events that we need to + * dispatch in order to keep going are never read. + */ +namespace +{ +void DispatchPendingEvents(IDllWaylandClient &clientLibrary, + struct wl_display *display) +{ + clientLibrary.wl_display_dispatch_pending(display); + /* We flush the output queue in the main thread as that needs to + * happen after eglSwapBuffers */ +} + +void ReadAndDispatch(IDllWaylandClient &clientLibrary, + struct wl_display *display) +{ + clientLibrary.wl_display_dispatch(display); +} +} + +xw11::EventQueueStrategy::EventQueueStrategy(IDllWaylandClient &clientLibrary, + struct wl_display *display) : + m_clientLibrary(clientLibrary), + m_display(display), + m_thread(boost::bind(ReadAndDispatch, + boost::ref(m_clientLibrary), + m_display), + boost::bind(DispatchPendingEvents, + boost::ref(m_clientLibrary), + m_display), + m_clientLibrary.wl_display_get_fd(m_display)) +{ +} + +namespace +{ +void ExecuteAction(const xwe::IEventQueueStrategy::Action &action) +{ + action(); +} +} + +void +xw11::EventQueueStrategy::DispatchEventsFromMain() +{ + unsigned int numActions = 0; + std::vector pendingActions; + + /* We only need to hold the lock while we copy out actions from the + * queue */ + { + CSingleLock lock(m_actionsMutex); + numActions = m_actions.size(); + pendingActions.reserve(numActions); + + /* Only pump the initial queued event count otherwise if the UI + * keeps pushing events then the loop won't finish */ + for (unsigned int index = 0; index < numActions; ++index) + { + pendingActions.push_back(m_actions.front()); + m_actions.pop(); + } + } + + /* Execute each of the queued up actions */ + std::for_each(pendingActions.begin(), + pendingActions.end(), + ExecuteAction); + + /* After we've done dispatching flush the event queue */ + m_clientLibrary.wl_display_flush(m_display); +} + +void +xw11::EventQueueStrategy::PushAction(const Action &action) +{ + CSingleLock lock(m_actionsMutex); + m_actions.push(action); +} diff --git a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h new file mode 100644 index 0000000000000..e6c394555e46f --- /dev/null +++ b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h @@ -0,0 +1,79 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +#include "threads/CriticalSection.h" +#include "EventQueueStrategy.h" +#include "PollThread.h" + +class IDllWaylandClient; + +struct wl_display; + +namespace xbmc +{ +namespace wayland +{ +namespace version_11 +{ +/* The EventQueueStrategy for Wayland <= 1.1 requires that events + * be dispatched and initally processed in a separate thread. This + * means that all the wayland proxy object wrappers callbacks will + * be running in the same thread that reads the event queue for events. + * + * When those events are initially processed, they will be put into the + * main WaylandEventLoop queue and dispatched sequentially from there + * periodically (once every redraw) into the main thread. + * + * The reason for this is that Wayland versions prior to 1.1 provide + * no means to read the event queue without also dispatching pending + * events and callbacks on proxy objects. But we also cannot block the + * main thread, which may occurr if we call wl_display_dispatch + * and there is no pending frame callback because our surface is not + * visible. + */ +class EventQueueStrategy : + public events::IEventQueueStrategy +{ +public: + + EventQueueStrategy(IDllWaylandClient &clientLibrary, + struct wl_display *display); + + void PushAction(const Action &action); + void DispatchEventsFromMain(); + +private: + + IDllWaylandClient &m_clientLibrary; + struct wl_display *m_display; + + events::PollThread m_thread; + + CCriticalSection m_actionsMutex; + std::queue m_actions; +}; +} +} +} diff --git a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp new file mode 100644 index 0000000000000..93cf18cc07e36 --- /dev/null +++ b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include +#include +#include + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "windowing/DllWaylandClient.h" +#include "utils/log.h" + +#include "Wayland12EventQueueStrategy.h" + +namespace xw12 = xbmc::wayland::version_12; + +namespace +{ +/* Pending events dispatch happens in the main thread, so there is + * no before-poll action that occurrs here */ +void Nothing() +{ +} + +void Read(IDllWaylandClient &clientLibrary, + struct wl_display *display) +{ + /* If wl_display_prepare_read() returns a nonzero value it means + * that we still have more events to dispatch. So let the main thread + * dispatch all the pending events first before trying to read + * more events from the pipe */ + if ((*(clientLibrary.wl_display_prepare_read_proc()))(display) == 0) + (*(clientLibrary.wl_display_read_events_proc()))(display); +} +} + +xw12::EventQueueStrategy::EventQueueStrategy(IDllWaylandClient &clientLibrary, + struct wl_display *display) : + m_clientLibrary(clientLibrary), + m_display(display), + m_thread(boost::bind(Read, boost::ref(m_clientLibrary), display), + boost::bind(Nothing), + m_clientLibrary.wl_display_get_fd(m_display)) +{ +} + +void +xw12::EventQueueStrategy::DispatchEventsFromMain() +{ + /* It is very important that these functions occurr in the order. + * that they are written below. Deadlocks might occurr otherwise. + * + * The first function dispatches any pending events that have been + * determined from prior reads of the event queue without *also* + * reading the event queue. + * + * The second function function flushes the output buffer so that our + * just-dispatched events will cause data to be processed on the + * compositor which results in more events for us to read. + * + * The input buffer will be read periodically (on the render loop, + * which never sleeps) + * + * If the functions are not called in this order, you might run into + * a situation where pending-dispatch events might have generated a + * write to the event queue in order to keep us awake (frame events + * are a particular culprit here), or where events that we need to + * dispatch in order to keep going are never read. + */ + m_clientLibrary.wl_display_dispatch_pending(m_display); + /* We perform the flush here and not in the reader thread + * as it needs to come after eglSwapBuffers */ + m_clientLibrary.wl_display_flush(m_display); +} + +void +xw12::EventQueueStrategy::PushAction(const Action &action) +{ + action(); +} diff --git a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h new file mode 100644 index 0000000000000..584e0117f1672 --- /dev/null +++ b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h @@ -0,0 +1,59 @@ +#pragma once + +/* + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#include + +#include + +#include "EventQueueStrategy.h" +#include "PollThread.h" + +class IDllWaylandClient; + +struct wl_display; + +namespace xbmc +{ +namespace wayland +{ +namespace version_12 +{ +class EventQueueStrategy : + public events::IEventQueueStrategy +{ +public: + + EventQueueStrategy(IDllWaylandClient &clientLibrary, + struct wl_display *display); + + void PushAction(const Action &action); + void DispatchEventsFromMain(); + +private: + + IDllWaylandClient &m_clientLibrary; + struct wl_display *m_display; + + events::PollThread m_thread; +}; +} +} +} From b8c015440bee96897b6fc5c9320d7fc7910f2f81 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 25/59] system_egl.h: new header wrapping EGL/egl.h It is important to define WL_EGL_PLATFORM prior to including EGL/egl.h if Wayland is used, because the headers default to X11. Signed-off-by: memeka --- .../DVDCodecs/Video/OpenMaxVideo.h | 2 +- .../cores/VideoPlayer/DVDCodecs/Video/VAAPI.h | 2 +- xbmc/cores/omxplayer/OMXImage.h | 2 +- xbmc/system_egl.h | 33 +++++++++++++++++++ xbmc/windowing/egl/EGLNativeTypeWayland.h | 2 +- xbmc/windowing/egl/EGLWrapper.h | 2 +- xbmc/windowing/egl/WinSystemEGL.h | 2 +- 7 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 xbmc/system_egl.h diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h index cf569c0d89b91..5ca7a1c93250a 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/OpenMaxVideo.h @@ -24,7 +24,7 @@ #include #include "OpenMax.h" -#include +#include "system_egl.h" #include #include #include diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h index 7f62cfe33eada..cf483d4b07bcf 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h @@ -20,7 +20,7 @@ #pragma once #include "system_gl.h" -#include +#include "system_egl.h" #include #include "DVDVideoCodec.h" diff --git a/xbmc/cores/omxplayer/OMXImage.h b/xbmc/cores/omxplayer/OMXImage.h index a93aa82663903..06039f5626f51 100644 --- a/xbmc/cores/omxplayer/OMXImage.h +++ b/xbmc/cores/omxplayer/OMXImage.h @@ -35,7 +35,7 @@ #endif #include "system_gl.h" -#include +#include "system_egl.h" #include #include "threads/Thread.h" diff --git a/xbmc/system_egl.h b/xbmc/system_egl.h new file mode 100644 index 0000000000000..68adf3072b3c5 --- /dev/null +++ b/xbmc/system_egl.h @@ -0,0 +1,33 @@ +#pragma once + +/* + * Copyright (C) 2005-2016 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" + +#ifndef HAS_EGL +#error EGL is disabled +#endif + +#ifdef HAVE_WAYLAND +#define WL_EGL_PLATFORM +#endif + +#include diff --git a/xbmc/windowing/egl/EGLNativeTypeWayland.h b/xbmc/windowing/egl/EGLNativeTypeWayland.h index 301c16c53b615..344d4be23738f 100644 --- a/xbmc/windowing/egl/EGLNativeTypeWayland.h +++ b/xbmc/windowing/egl/EGLNativeTypeWayland.h @@ -22,7 +22,7 @@ #include -#include +#include "system_egl.h" #include "EGLNativeType.h" class CEGLNativeTypeWayland : public CEGLNativeType diff --git a/xbmc/windowing/egl/EGLWrapper.h b/xbmc/windowing/egl/EGLWrapper.h index 9fec9d4d3c684..16869694cdb03 100644 --- a/xbmc/windowing/egl/EGLWrapper.h +++ b/xbmc/windowing/egl/EGLWrapper.h @@ -24,7 +24,7 @@ #include #include "guilib/Resolution.h" -#include +#include "system_egl.h" class CEGLNativeType; class CEGLWrapper { diff --git a/xbmc/windowing/egl/WinSystemEGL.h b/xbmc/windowing/egl/WinSystemEGL.h index c24bb356b94e1..50416b59aece1 100644 --- a/xbmc/windowing/egl/WinSystemEGL.h +++ b/xbmc/windowing/egl/WinSystemEGL.h @@ -28,7 +28,7 @@ #include "rendering/gles/RenderSystemGLES.h" #include "utils/GlobalsHandling.h" -#include +#include "system_egl.h" #include "windowing/WinSystem.h" #include "threads/SystemClock.h" From ee9297c519531e6c0b5f3ce159c036c6aae90678 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 26/59] Windowing/EGL: add method GetWaylandDisplay() Signed-off-by: memeka --- xbmc/windowing/egl/EGLWrapper.cpp | 17 +++++++++++++++++ xbmc/windowing/egl/EGLWrapper.h | 4 ++++ xbmc/windowing/egl/WinSystemEGL.cpp | 9 +++++++++ xbmc/windowing/egl/WinSystemEGL.h | 5 +++++ 4 files changed, 35 insertions(+) diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp index c058f2cc55fd6..3da8f78eee968 100644 --- a/xbmc/windowing/egl/EGLWrapper.cpp +++ b/xbmc/windowing/egl/EGLWrapper.cpp @@ -173,6 +173,23 @@ void CEGLWrapper::DestroyNativeWindow() m_nativeTypes->DestroyNativeWindow(); } +#ifdef HAVE_WAYLAND + +struct wl_display *CEGLWrapper::GetWaylandDisplay() +{ + auto *wl = dynamic_cast(m_nativeTypes); + if (!wl) + return NULL; + + EGLNativeDisplayType *nativeDisplay = NULL; + if (!m_nativeTypes->GetNativeDisplay((XBNativeDisplayType**)&nativeDisplay)) + return NULL; + + return *nativeDisplay; +} + +#endif + bool CEGLWrapper::SetNativeResolution(RESOLUTION_INFO& res) { if (!m_nativeTypes) diff --git a/xbmc/windowing/egl/EGLWrapper.h b/xbmc/windowing/egl/EGLWrapper.h index 16869694cdb03..d3e7cae072953 100644 --- a/xbmc/windowing/egl/EGLWrapper.h +++ b/xbmc/windowing/egl/EGLWrapper.h @@ -41,6 +41,10 @@ class CEGLWrapper void DestroyNativeDisplay(); void DestroyNativeWindow(); +#ifdef HAVE_WAYLAND + struct wl_display *GetWaylandDisplay(); +#endif + bool SetNativeResolution(RESOLUTION_INFO& res); bool ProbeResolutions(std::vector &resolutions); bool ShowWindow(bool show); diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp index 60a1a8dce7a39..933dc9bec5b3d 100644 --- a/xbmc/windowing/egl/WinSystemEGL.cpp +++ b/xbmc/windowing/egl/WinSystemEGL.cpp @@ -555,6 +555,15 @@ EGLConfig CWinSystemEGL::GetEGLConfig() return m_config; } +#ifdef HAVE_WAYLAND + +struct wl_display *CWinSystemEGL::GetWaylandDisplay() +{ + return m_egl->GetWaylandDisplay(); +} + +#endif + bool CWinSystemEGL::ClampToGUIDisplayLimits(int &width, int &height) { width = width > m_nWidth ? m_nWidth : width; diff --git a/xbmc/windowing/egl/WinSystemEGL.h b/xbmc/windowing/egl/WinSystemEGL.h index 50416b59aece1..f98487b1623a5 100644 --- a/xbmc/windowing/egl/WinSystemEGL.h +++ b/xbmc/windowing/egl/WinSystemEGL.h @@ -69,6 +69,11 @@ class CWinSystemEGL : public CWinSystemBase, public CRenderSystemGLES EGLDisplay GetEGLDisplay(); EGLContext GetEGLContext(); + +#ifdef HAVE_WAYLAND + struct wl_display *GetWaylandDisplay(); +#endif + protected: virtual void PresentRenderImpl(bool rendered); virtual void SetVSyncImpl(bool enable); From c787165d925b161853c0f2bc6ae6e686e778d345 Mon Sep 17 00:00:00 2001 From: memeka Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 27/59] WINDOW_SYSTEM: add Wayland Signed-off-by: memeka --- xbmc/windowing/WinSystem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h index 08c28a3620849..e4e86ddf801f4 100644 --- a/xbmc/windowing/WinSystem.h +++ b/xbmc/windowing/WinSystem.h @@ -31,6 +31,7 @@ typedef enum _WindowSystemType WINDOW_SYSTEM_OSX, WINDOW_SYSTEM_IOS, WINDOW_SYSTEM_X11, + WINDOW_SYSTEM_WAYLAND, WINDOW_SYSTEM_SDL, WINDOW_SYSTEM_EGL, WINDOW_SYSTEM_ANDROID From 6bc544139b898198326c5faaa55903401ddefb42 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 28/59] Wayland: replace Boost with C++11 standard library Signed-off-by: memeka --- xbmc/windowing/WinEventsWayland.cpp | 8 ++-- xbmc/windowing/egl/EGLNativeTypeWayland.cpp | 14 ++---- xbmc/windowing/egl/EGLNativeTypeWayland.h | 6 +-- xbmc/windowing/egl/wayland/Callback.cpp | 3 -- xbmc/windowing/egl/wayland/Callback.h | 11 ++--- xbmc/windowing/egl/wayland/Compositor.h | 8 ++-- xbmc/windowing/egl/wayland/Display.cpp | 6 +-- xbmc/windowing/egl/wayland/Display.h | 15 ++++--- xbmc/windowing/egl/wayland/OpenGLSurface.h | 7 +-- xbmc/windowing/egl/wayland/Output.h | 8 ++-- xbmc/windowing/egl/wayland/Region.h | 7 +-- xbmc/windowing/egl/wayland/Registry.cpp | 4 +- xbmc/windowing/egl/wayland/Registry.h | 22 ++++----- xbmc/windowing/egl/wayland/Shell.h | 7 +-- xbmc/windowing/egl/wayland/ShellSurface.h | 8 ++-- xbmc/windowing/egl/wayland/Surface.cpp | 4 +- xbmc/windowing/egl/wayland/Surface.h | 15 ++++--- xbmc/windowing/egl/wayland/WaylandLibraries.h | 17 ++++--- xbmc/windowing/egl/wayland/XBMCConnection.cpp | 45 +++++++++---------- xbmc/windowing/egl/wayland/XBMCConnection.h | 5 +-- xbmc/windowing/egl/wayland/XBMCSurface.cpp | 29 ++++++------ xbmc/windowing/egl/wayland/XBMCSurface.h | 4 +- .../wayland/TestEGLNativeTypeWayland.cpp | 19 ++++---- .../TestXBMCWaylandInputAcceptance.cpp | 42 +++++++++-------- xbmc/windowing/tests/wayland/TmpEnv.h | 7 +-- .../windowing/tests/wayland/WestonProcess.cpp | 1 - xbmc/windowing/tests/wayland/WestonProcess.h | 8 ++-- xbmc/windowing/tests/wayland/WestonTest.cpp | 24 ++++++---- xbmc/windowing/tests/wayland/WestonTest.h | 3 +- xbmc/windowing/tests/wayland/XBMCWayland.h | 8 ++-- .../wayland/XBMCWaylandTestExtension.cpp | 41 +++++++++-------- xbmc/windowing/wayland/EventLoop.cpp | 22 +++++---- xbmc/windowing/wayland/EventLoop.h | 5 +-- xbmc/windowing/wayland/EventQueueStrategy.h | 13 +++--- xbmc/windowing/wayland/InputFactory.cpp | 4 -- xbmc/windowing/wayland/InputFactory.h | 9 ++-- xbmc/windowing/wayland/Keyboard.cpp | 12 ++--- xbmc/windowing/wayland/Keyboard.h | 28 +++++++----- xbmc/windowing/wayland/KeyboardProcessor.cpp | 10 +---- xbmc/windowing/wayland/KeyboardProcessor.h | 1 - xbmc/windowing/wayland/Pointer.h | 2 - xbmc/windowing/wayland/PollThread.cpp | 5 +-- xbmc/windowing/wayland/PollThread.h | 7 ++- xbmc/windowing/wayland/Seat.h | 8 ++-- xbmc/windowing/wayland/TimeoutManager.h | 8 ++-- .../wayland/Wayland11EventQueueStrategy.cpp | 17 +++---- .../wayland/Wayland11EventQueueStrategy.h | 2 - .../wayland/Wayland12EventQueueStrategy.cpp | 8 ++-- .../wayland/Wayland12EventQueueStrategy.h | 2 - 49 files changed, 274 insertions(+), 295 deletions(-) diff --git a/xbmc/windowing/WinEventsWayland.cpp b/xbmc/windowing/WinEventsWayland.cpp index d46870cbde919..6913be664c5b6 100644 --- a/xbmc/windowing/WinEventsWayland.cpp +++ b/xbmc/windowing/WinEventsWayland.cpp @@ -21,8 +21,6 @@ #if defined (HAVE_WAYLAND) -#include - #include "Application.h" #include "xbmc/windowing/WindowingFactory.h" #include "WinEventsWayland.h" @@ -31,6 +29,8 @@ #include "wayland/InputFactory.h" #include "wayland/EventLoop.h" +#include + namespace xwe = xbmc::wayland::events; namespace @@ -46,8 +46,8 @@ class XBMCListener : }; XBMCListener g_listener; -boost::scoped_ptr g_inputInstance; -boost::scoped_ptr g_eventLoop; +std::unique_ptr g_inputInstance; +std::unique_ptr g_eventLoop; } void XBMCListener::OnEvent(XBMC_Event &e) diff --git a/xbmc/windowing/egl/EGLNativeTypeWayland.cpp b/xbmc/windowing/egl/EGLNativeTypeWayland.cpp index ef45bb1567408..06a3188b2dd60 100644 --- a/xbmc/windowing/egl/EGLNativeTypeWayland.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeWayland.cpp @@ -27,12 +27,6 @@ #include #include -#include -#include -#include -#include -#include - #include #include @@ -63,9 +57,9 @@ class CEGLNativeTypeWayland::Private { public: - boost::scoped_ptr m_libraries; - boost::scoped_ptr m_connection; - boost::scoped_ptr m_surface; + std::unique_ptr m_libraries; + std::unique_ptr m_connection; + std::unique_ptr m_surface; bool LoadWaylandLibraries(); void UnloadWaylandLibraries(); @@ -274,7 +268,7 @@ bool CEGLNativeTypeWayland::GetNativeWindow(XBNativeDisplayType **nativeWindow) } /* DestroyNativeDisplay and DestroyNativeWindow simply just call - * reset on the relevant scoped_ptr. This will effectively destroy + * reset on the relevant unique_ptr. This will effectively destroy * the encapsulating objects which cleans up all of the relevant * connections and surfaces */ bool CEGLNativeTypeWayland::DestroyNativeDisplay() diff --git a/xbmc/windowing/egl/EGLNativeTypeWayland.h b/xbmc/windowing/egl/EGLNativeTypeWayland.h index 344d4be23738f..fd45c6a1d8e20 100644 --- a/xbmc/windowing/egl/EGLNativeTypeWayland.h +++ b/xbmc/windowing/egl/EGLNativeTypeWayland.h @@ -20,11 +20,11 @@ * */ -#include - #include "system_egl.h" #include "EGLNativeType.h" +#include + class CEGLNativeTypeWayland : public CEGLNativeType { public: @@ -54,5 +54,5 @@ class CEGLNativeTypeWayland : public CEGLNativeType class Private; - boost::scoped_ptr priv; + std::unique_ptr priv; }; diff --git a/xbmc/windowing/egl/wayland/Callback.cpp b/xbmc/windowing/egl/wayland/Callback.cpp index 45d0befa72c02..0055d1780538c 100644 --- a/xbmc/windowing/egl/wayland/Callback.cpp +++ b/xbmc/windowing/egl/wayland/Callback.cpp @@ -19,9 +19,6 @@ */ #include -#include -#include - #include "windowing/DllWaylandClient.h" #include "windowing/WaylandProtocol.h" #include "Callback.h" diff --git a/xbmc/windowing/egl/wayland/Callback.h b/xbmc/windowing/egl/wayland/Callback.h index 6ae6df21845dc..00fba8afd0ec2 100644 --- a/xbmc/windowing/egl/wayland/Callback.h +++ b/xbmc/windowing/egl/wayland/Callback.h @@ -19,8 +19,7 @@ * . * */ -#include -#include +#include #include @@ -35,18 +34,20 @@ namespace wayland * in time. A custom closure can be provided as func to be called * whenever this callback is fired */ -class Callback : - boost::noncopyable +class Callback { public: - typedef boost::function Func; + typedef std::function Func; Callback(IDllWaylandClient &clientLibrary, struct wl_callback *callback, const Func &func); ~Callback(); + Callback(const Callback &) = delete; + Callback &operator=(const Callback &) = delete; + struct wl_callback * GetWlCallback(); static const struct wl_callback_listener m_listener; diff --git a/xbmc/windowing/egl/wayland/Compositor.h b/xbmc/windowing/egl/wayland/Compositor.h index 93d2e8d1ed021..20be4141845b0 100644 --- a/xbmc/windowing/egl/wayland/Compositor.h +++ b/xbmc/windowing/egl/wayland/Compositor.h @@ -19,8 +19,6 @@ * . * */ -#include - struct wl_compositor; struct wl_surface; struct wl_region; @@ -31,8 +29,7 @@ namespace xbmc { namespace wayland { -class Compositor : - boost::noncopyable +class Compositor { public: @@ -40,6 +37,9 @@ class Compositor : struct wl_compositor *compositor); ~Compositor(); + Compositor(const Compositor &) = delete; + Compositor &operator=(const Compositor &) = delete; + struct wl_compositor * GetWlCompositor(); /* Creates a "surface" on the compositor. This is not a renderable diff --git a/xbmc/windowing/egl/wayland/Display.cpp b/xbmc/windowing/egl/wayland/Display.cpp index 52f7c1fdaa66f..bd6076a6ba3c3 100644 --- a/xbmc/windowing/egl/wayland/Display.cpp +++ b/xbmc/windowing/egl/wayland/Display.cpp @@ -21,8 +21,6 @@ #include #include -#include - #include #include @@ -42,7 +40,7 @@ xw::WaylandDisplayListener::SetHandler(const Handler &handler) void xw::WaylandDisplayListener::DisplayAvailable(Display &display) { - if (!m_handler.empty()) + if (m_handler) m_handler(display); } @@ -55,7 +53,7 @@ xw::WaylandDisplayListener::GetInstance() return *m_instance; } -boost::scoped_ptr xw::WaylandDisplayListener::m_instance; +std::unique_ptr xw::WaylandDisplayListener::m_instance; xw::Display::Display(IDllWaylandClient &clientLibrary) : m_clientLibrary(clientLibrary), diff --git a/xbmc/windowing/egl/wayland/Display.h b/xbmc/windowing/egl/wayland/Display.h index 882d90cde8ecb..987e8116a00ba 100644 --- a/xbmc/windowing/egl/wayland/Display.h +++ b/xbmc/windowing/egl/wayland/Display.h @@ -19,9 +19,8 @@ * . * */ -#include -#include -#include +#include +#include class IDllWaylandClient; @@ -34,14 +33,16 @@ namespace xbmc { namespace wayland { -class Display : - boost::noncopyable +class Display { public: Display(IDllWaylandClient &clientLibrary); ~Display(); + Display(const Display &) = delete; + Display &operator=(const Display &) = delete; + struct wl_display * GetWlDisplay(); EGLNativeDisplayType* GetEGLNativeDisplay(); struct wl_callback * Sync(); @@ -59,7 +60,7 @@ class WaylandDisplayListener { public: - typedef boost::function Handler; + typedef std::function Handler; void SetHandler(const Handler &); void DisplayAvailable(Display &); @@ -69,7 +70,7 @@ class WaylandDisplayListener Handler m_handler; - static boost::scoped_ptr m_instance; + static std::unique_ptr m_instance; }; } } diff --git a/xbmc/windowing/egl/wayland/OpenGLSurface.h b/xbmc/windowing/egl/wayland/OpenGLSurface.h index 288dbbf1962c1..58c880ab63384 100644 --- a/xbmc/windowing/egl/wayland/OpenGLSurface.h +++ b/xbmc/windowing/egl/wayland/OpenGLSurface.h @@ -19,7 +19,6 @@ * . * */ -#include class IDllWaylandEGL; @@ -32,8 +31,7 @@ namespace xbmc { namespace wayland { -class OpenGLSurface : - boost::noncopyable +class OpenGLSurface { public: @@ -43,6 +41,9 @@ class OpenGLSurface : int32_t height); ~OpenGLSurface(); + OpenGLSurface(const OpenGLSurface &) = delete; + OpenGLSurface &operator=(const OpenGLSurface &) = delete; + struct wl_egl_window * GetWlEglWindow(); EGLNativeWindowType * GetEGLNativeWindow(); void Resize(int width, int height); diff --git a/xbmc/windowing/egl/wayland/Output.h b/xbmc/windowing/egl/wayland/Output.h index 9743b68b224fb..b143c98db1193 100644 --- a/xbmc/windowing/egl/wayland/Output.h +++ b/xbmc/windowing/egl/wayland/Output.h @@ -21,8 +21,6 @@ */ #include -#include - #include class IDllWaylandClient; @@ -31,8 +29,7 @@ namespace xbmc { namespace wayland { -struct Output : - boost::noncopyable +struct Output { public: @@ -40,6 +37,9 @@ struct Output : struct wl_output *); ~Output(); + Output(const Output &) = delete; + Output &operator=(const Output &) = delete; + struct ModeGeometry { int32_t width; diff --git a/xbmc/windowing/egl/wayland/Region.h b/xbmc/windowing/egl/wayland/Region.h index d9ec1497831da..60629c6908a0c 100644 --- a/xbmc/windowing/egl/wayland/Region.h +++ b/xbmc/windowing/egl/wayland/Region.h @@ -19,7 +19,6 @@ * . * */ -#include class IDllWaylandClient; @@ -29,14 +28,16 @@ namespace xbmc { namespace wayland { -class Region : - boost::noncopyable +class Region { public: Region(IDllWaylandClient &clientLibrary, struct wl_region *); ~Region(); + + Region(const Region &) = delete; + Region &operator=(const Region &) = delete; struct wl_region * GetWlRegion(); diff --git a/xbmc/windowing/egl/wayland/Registry.cpp b/xbmc/windowing/egl/wayland/Registry.cpp index 2a433f3526e2b..322d883df07d8 100644 --- a/xbmc/windowing/egl/wayland/Registry.cpp +++ b/xbmc/windowing/egl/wayland/Registry.cpp @@ -44,7 +44,7 @@ xw::ExtraWaylandGlobals::NewGlobal(struct wl_registry *registry, const char *interface, uint32_t version) { - if (!m_handler.empty()) + if (m_handler) m_handler(registry, name, interface, version); } @@ -57,7 +57,7 @@ xw::ExtraWaylandGlobals::GetInstance() return *m_instance; } -boost::scoped_ptr xw::ExtraWaylandGlobals::m_instance; +std::unique_ptr xw::ExtraWaylandGlobals::m_instance; /* We inject an IWaylandRegistration here which is a virtual * class which a callback for the global objects diff --git a/xbmc/windowing/egl/wayland/Registry.h b/xbmc/windowing/egl/wayland/Registry.h index 61ce455c45e79..8af1a855a302e 100644 --- a/xbmc/windowing/egl/wayland/Registry.h +++ b/xbmc/windowing/egl/wayland/Registry.h @@ -20,10 +20,8 @@ * */ #include - -#include -#include -#include +#include +#include #include @@ -42,10 +40,10 @@ class ExtraWaylandGlobals { public: - typedef boost::function GlobalHandler; + typedef std::function GlobalHandler; void SetHandler(const GlobalHandler &); void NewGlobal(struct wl_registry *, @@ -58,7 +56,7 @@ class ExtraWaylandGlobals GlobalHandler m_handler; - static boost::scoped_ptr m_instance; + static std::unique_ptr m_instance; }; class IWaylandRegistration @@ -72,8 +70,7 @@ class IWaylandRegistration uint32_t) = 0; }; -class Registry : - boost::noncopyable +class Registry { public: @@ -82,6 +79,9 @@ class Registry : IWaylandRegistration ®istration); ~Registry(); + Registry(const Registry &) = delete; + Registry &operator=(const Registry &) = delete; + struct wl_registry * GetWlRegistry(); template diff --git a/xbmc/windowing/egl/wayland/Shell.h b/xbmc/windowing/egl/wayland/Shell.h index 4e5c19ce1e9db..8cc7911ab6628 100644 --- a/xbmc/windowing/egl/wayland/Shell.h +++ b/xbmc/windowing/egl/wayland/Shell.h @@ -19,7 +19,6 @@ * . * */ -#include class IDllWaylandClient; @@ -31,8 +30,7 @@ namespace xbmc { namespace wayland { -class Shell : - boost::noncopyable +class Shell { public: @@ -40,6 +38,9 @@ class Shell : struct wl_shell *shell); ~Shell(); + Shell(const Shell &) = delete; + Shell &operator=(const Shell &) = delete; + struct wl_shell * GetWlShell(); struct wl_shell_surface * CreateShellSurface(struct wl_surface *); diff --git a/xbmc/windowing/egl/wayland/ShellSurface.h b/xbmc/windowing/egl/wayland/ShellSurface.h index eeadd41466d64..48acbac639274 100644 --- a/xbmc/windowing/egl/wayland/ShellSurface.h +++ b/xbmc/windowing/egl/wayland/ShellSurface.h @@ -21,16 +21,13 @@ */ #include -#include - class IDllWaylandClient; namespace xbmc { namespace wayland { -class ShellSurface : - boost::noncopyable +class ShellSurface { public: @@ -38,6 +35,9 @@ class ShellSurface : struct wl_shell_surface *shellSurface); ~ShellSurface(); + ShellSurface(const ShellSurface &) = delete; + ShellSurface &operator=(const ShellSurface &) = delete; + struct wl_shell_surface * GetWlShellSurface(); void SetFullscreen(enum wl_shell_surface_fullscreen_method method, uint32_t framerate, diff --git a/xbmc/windowing/egl/wayland/Surface.cpp b/xbmc/windowing/egl/wayland/Surface.cpp index 9e787c75c8cd6..9082d3032bb47 100644 --- a/xbmc/windowing/egl/wayland/Surface.cpp +++ b/xbmc/windowing/egl/wayland/Surface.cpp @@ -25,7 +25,7 @@ namespace xw = xbmc::wayland; -boost::scoped_ptr xw::WaylandSurfaceListener::m_instance; +std::unique_ptr xw::WaylandSurfaceListener::m_instance; xw::WaylandSurfaceListener & xw::WaylandSurfaceListener::GetInstance() @@ -45,7 +45,7 @@ xw::WaylandSurfaceListener::SetHandler(const Handler &handler) void xw::WaylandSurfaceListener::SurfaceCreated(xw::Surface &surface) { - if (!m_handler.empty()) + if (m_handler) m_handler(surface); } diff --git a/xbmc/windowing/egl/wayland/Surface.h b/xbmc/windowing/egl/wayland/Surface.h index 358978d324976..090b0159fd325 100644 --- a/xbmc/windowing/egl/wayland/Surface.h +++ b/xbmc/windowing/egl/wayland/Surface.h @@ -19,9 +19,8 @@ * . * */ -#include -#include -#include +#include +#include struct wl_surface; struct wl_callback; @@ -33,8 +32,7 @@ namespace xbmc { namespace wayland { -class Surface : - boost::noncopyable +class Surface { public: @@ -42,6 +40,9 @@ class Surface : struct wl_surface *surface); ~Surface(); + Surface(const Surface &) = delete; + Surface &operator=(const Surface &) = delete; + struct wl_surface * GetWlSurface(); struct wl_callback * CreateFrameCallback(); void SetOpaqueRegion(struct wl_region *region); @@ -62,7 +63,7 @@ class WaylandSurfaceListener { public: - typedef boost::function Handler; + typedef std::function Handler; void SetHandler(const Handler &); void SurfaceCreated(Surface &); @@ -72,7 +73,7 @@ class WaylandSurfaceListener Handler m_handler; - static boost::scoped_ptr m_instance; + static std::unique_ptr m_instance; }; } } diff --git a/xbmc/windowing/egl/wayland/WaylandLibraries.h b/xbmc/windowing/egl/wayland/WaylandLibraries.h index 3c7193d869be2..d4ac7ee299b18 100644 --- a/xbmc/windowing/egl/wayland/WaylandLibraries.h +++ b/xbmc/windowing/egl/wayland/WaylandLibraries.h @@ -19,8 +19,6 @@ * . * */ -#include - #include "windowing/DllWaylandClient.h" #include "windowing/DllWaylandEgl.h" #include "windowing/DllXKBCommon.h" @@ -30,13 +28,16 @@ namespace xbmc namespace wayland { template -class AutoloadDll : - boost::noncopyable +class AutoloadDll { public: AutoloadDll(); ~AutoloadDll(); + + AutoloadDll(const AutoloadDll &) = delete; + AutoloadDll &operator=(const AutoloadDll &) = delete; + DllInterface & Get(); private: @@ -44,11 +45,15 @@ class AutoloadDll : Dll m_dll; }; -class Libraries : - boost::noncopyable +class Libraries { public: + Libraries() = default; + + Libraries(const Libraries &) = delete; + Libraries &operator=(const Libraries &) = delete; + IDllWaylandClient & ClientLibrary(); IDllWaylandEGL & EGLLibrary(); IDllXKBCommon & XKBCommonLibrary(); diff --git a/xbmc/windowing/egl/wayland/XBMCConnection.cpp b/xbmc/windowing/egl/wayland/XBMCConnection.cpp index 7b1b4672afd27..a6b823a2b8106 100644 --- a/xbmc/windowing/egl/wayland/XBMCConnection.cpp +++ b/xbmc/windowing/egl/wayland/XBMCConnection.cpp @@ -21,12 +21,8 @@ #include #include #include - -#include -#include -#include -#include -#include +#include +#include #include @@ -89,7 +85,7 @@ class GlobalInterface : { public: - typedef boost::function AvailabilityHook; + typedef std::function AvailabilityHook; protected: @@ -167,8 +163,8 @@ class StoredGlobalInterface : { public: - typedef boost::function Factory; - typedef std::vector > Implementations; + typedef std::function Factory; + typedef std::vector > Implementations; /* Factory must be capable of returning a new Implementation * * corresponding to a WaylandImplementation *. This is usually @@ -262,7 +258,7 @@ class XBMCConnection::Private : /* Synchronization logic - these variables should not be touched * outside the scope of WaitForSynchronize() */ bool synchronized; - boost::scoped_ptr synchronizeCallback; + std::unique_ptr synchronizeCallback; bool OnGlobalInterfaceAvailable(uint32_t name, const char *interface, @@ -270,15 +266,15 @@ class XBMCConnection::Private : void InjectSeat(); - boost::scoped_ptr m_display; - boost::scoped_ptr m_registry; + std::unique_ptr m_display; + std::unique_ptr m_registry; StoredGlobalInterface m_compositor; StoredGlobalInterface m_shell; WaylandGlobalObject m_seat; StoredGlobalInterface m_outputs; - boost::scoped_ptr m_eventQueue; + std::unique_ptr m_eventQueue; }; } } @@ -294,7 +290,7 @@ xw::GlobalInterface::OnObjectAvailable(uint32_t name, m_availableNames.push(name); m_version = version; - if (!m_hook.empty()) + if (m_hook) m_hook(m_version); } @@ -356,7 +352,7 @@ xw::StoredGlobalInterface::Get(Registry & while (proxy) { - boost::shared_ptr instance(m_factory(proxy)); + std::shared_ptr instance(m_factory(proxy)); m_implementations.push_back(instance); proxy = m_waylandObject.FetchPending(registry); } @@ -518,16 +514,17 @@ xw::XBMCConnection::Private::Private(IDllWaylandClient &clientLibrary, m_registry(new xw::Registry(clientLibrary, m_display->GetWlDisplay(), *this)), - m_compositor(boost::bind(CreateCompositor, _1, &m_clientLibrary), + m_compositor(std::bind(CreateCompositor, std::placeholders::_1, + &m_clientLibrary), RequestedCompositorVersion, clientLibrary.Get_wl_compositor_interface()), - m_shell(boost::bind(CreateShell, _1, &m_clientLibrary), + m_shell(std::bind(CreateShell, std::placeholders::_1, &m_clientLibrary), RequestedShellVersion, clientLibrary.Get_wl_shell_interface()), m_seat(RequestedSeatVersion, clientLibrary.Get_wl_seat_interface(), - boost::bind(&Private::InjectSeat, this)), - m_outputs(boost::bind(CreateOutput, _1, &m_clientLibrary), + std::bind(&Private::InjectSeat, this)), + m_outputs(std::bind(CreateOutput, std::placeholders::_1, &m_clientLibrary), RequestedOutputVersion, clientLibrary.Get_wl_output_interface()), m_eventQueue(EventQueueForClientVersion(m_clientLibrary, @@ -569,7 +566,7 @@ xw::XBMCConnection::XBMCConnection(IDllWaylandClient &clientLibrary, } /* A defined destructor is required such that - * boost::scoped_ptr::~scoped_ptr is generated here */ + * std::unique_ptr::~unique_ptr is generated here */ xw::XBMCConnection::~XBMCConnection() { } @@ -619,9 +616,9 @@ xw::XBMCConnection::Private::OnGlobalInterfaceAvailable(uint32_t name, const char *interface, uint32_t version) { - /* A boost::array is effectively immutable so we can leave out + /* A std::array is effectively immutable so we can leave out * const here */ - typedef boost::array ConstructorArray; + typedef std::array ConstructorArray; /* Not static, as the pointers here may change in cases where @@ -657,8 +654,8 @@ xw::XBMCConnection::Private::OnGlobalInterfaceAvailable(uint32_t name, void xw::XBMCConnection::Private::WaitForSynchronize() { - boost::function func(boost::bind(&Private::Synchronize, - this)); + std::function func(std::bind(&Private::Synchronize, + this)); synchronized = false; synchronizeCallback.reset(new xw::Callback(m_clientLibrary, diff --git a/xbmc/windowing/egl/wayland/XBMCConnection.h b/xbmc/windowing/egl/wayland/XBMCConnection.h index 4e1477aa6790d..ca6dccb641b2b 100644 --- a/xbmc/windowing/egl/wayland/XBMCConnection.h +++ b/xbmc/windowing/egl/wayland/XBMCConnection.h @@ -19,8 +19,7 @@ * . * */ -#include -#include +#include class IDllWaylandClient; class IDllXKBCommon; @@ -87,7 +86,7 @@ class XBMCConnection private: class Private; - boost::scoped_ptr priv; + std::unique_ptr priv; }; } } diff --git a/xbmc/windowing/egl/wayland/XBMCSurface.cpp b/xbmc/windowing/egl/wayland/XBMCSurface.cpp index 18f565f4900a9..cdcab3ddaa1c7 100644 --- a/xbmc/windowing/egl/wayland/XBMCSurface.cpp +++ b/xbmc/windowing/egl/wayland/XBMCSurface.cpp @@ -19,11 +19,8 @@ */ #include #include - -#include -#include -#include -#include +#include +#include #include @@ -58,7 +55,7 @@ class XBMCSurface::Private uint32_t width, uint32_t height); - typedef boost::function RegionFactory; + typedef std::function RegionFactory; IDllWaylandClient &m_clientLibrary; IDllWaylandEGL &m_eglLibrary; @@ -70,10 +67,10 @@ class XBMCSurface::Private * a region later */ RegionFactory m_regionFactory; - boost::scoped_ptr m_surface; - boost::scoped_ptr m_shellSurface; - boost::scoped_ptr m_glSurface; - boost::scoped_ptr m_frameCallback; + std::unique_ptr m_surface; + std::unique_ptr m_shellSurface; + std::unique_ptr m_glSurface; + std::unique_ptr m_frameCallback; void OnFrameCallback(uint32_t); void AddFrameCallback(); @@ -103,8 +100,8 @@ xw::XBMCSurface::Private::Private(IDllWaylandClient &clientLibrary, m_clientLibrary(clientLibrary), m_eglLibrary(eglLibrary), m_eventInjector(eventInjector), - m_regionFactory(boost::bind(&Compositor::CreateRegion, - &compositor)), + m_regionFactory(std::bind(&Compositor::CreateRegion, + &compositor)), m_surface(new xw::Surface(m_clientLibrary, compositor.CreateSurface())), m_shellSurface(new xw::ShellSurface(m_clientLibrary, @@ -160,7 +157,7 @@ xw::XBMCSurface::XBMCSurface(IDllWaylandClient &clientLibrary, } /* A defined destructor is required such that - * boost::scoped_ptr::~scoped_ptr is generated here */ + * std::unique_ptr::~unique_ptr is generated here */ xw::XBMCSurface::~XBMCSurface() { } @@ -212,7 +209,7 @@ void xw::XBMCSurface::Private::AddFrameCallback() { m_frameCallback.reset(new xw::Callback(m_clientLibrary, m_surface->CreateFrameCallback(), - boost::bind(&Private::OnFrameCallback, - this, - _1))); + std::bind(&Private::OnFrameCallback, + this, + std::placeholders::_1))); } diff --git a/xbmc/windowing/egl/wayland/XBMCSurface.h b/xbmc/windowing/egl/wayland/XBMCSurface.h index c7d6531035c92..a9228d6b1002d 100644 --- a/xbmc/windowing/egl/wayland/XBMCSurface.h +++ b/xbmc/windowing/egl/wayland/XBMCSurface.h @@ -19,8 +19,6 @@ * . * */ -#include -#include class IDllWaylandClient; class IDllWaylandEGL; @@ -68,7 +66,7 @@ class XBMCSurface private: class Private; - boost::scoped_ptr priv; + std::unique_ptr priv; }; } } diff --git a/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp b/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp index 84a904e4efc3b..c0c88c1bf8da0 100644 --- a/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp +++ b/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp @@ -23,8 +23,7 @@ #include #include - -#include +#include #include @@ -125,12 +124,12 @@ class ConnectedEGLNativeTypeWaylandWestonTest : ConnectedEGLNativeTypeWaylandWestonTest::ConnectedEGLNativeTypeWaylandWestonTest() { xw::WaylandDisplayListener &displayListener(xw::WaylandDisplayListener::GetInstance()); - displayListener.SetHandler(boost::bind(&ConnectedEGLNativeTypeWaylandWestonTest::DisplayAvailable, - this, _1)); + displayListener.SetHandler(std::bind(&ConnectedEGLNativeTypeWaylandWestonTest::DisplayAvailable, + this, std::placeholders::_1)); xw::WaylandSurfaceListener &surfaceListener(xw::WaylandSurfaceListener::GetInstance()); - surfaceListener.SetHandler(boost::bind(&ConnectedEGLNativeTypeWaylandWestonTest::SurfaceCreated, - this, _1)); + surfaceListener.SetHandler(std::bind(&ConnectedEGLNativeTypeWaylandWestonTest::SurfaceCreated, + this, std::placeholders::_1)); } ConnectedEGLNativeTypeWaylandWestonTest::~ConnectedEGLNativeTypeWaylandWestonTest() @@ -207,14 +206,16 @@ class AssistedEGLNativeTypeWaylandTest : const char *interface, uint32_t version); - boost::scoped_ptr m_xbmcWayland; + std::unique_ptr m_xbmcWayland; }; AssistedEGLNativeTypeWaylandTest::AssistedEGLNativeTypeWaylandTest() { xw::ExtraWaylandGlobals &extra(xw::ExtraWaylandGlobals::GetInstance()); - extra.SetHandler(boost::bind(&AssistedEGLNativeTypeWaylandTest::Global, - this, _1, _2, _3, _4)); + extra.SetHandler(std::bind(&AssistedEGLNativeTypeWaylandTest::Global, + this, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3, + std::placeholders::_4)); } AssistedEGLNativeTypeWaylandTest::~AssistedEGLNativeTypeWaylandTest() diff --git a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp index 4f66ead2ada48..3e60565fb9cd2 100644 --- a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp +++ b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp @@ -20,10 +20,8 @@ #define WL_EGL_PLATFORM #include - -#include -#include -#include +#include +#include #include @@ -125,23 +123,23 @@ class InputEventsWestonTest : StubCursorManager cursors; StubEventListener listener; - boost::shared_ptr xkbContext; - boost::scoped_ptr keymap; + std::shared_ptr xkbContext; + std::unique_ptr keymap; - boost::scoped_ptr display; - boost::scoped_ptr queue; - boost::scoped_ptr registry; + std::unique_ptr display; + std::unique_ptr queue; + std::unique_ptr registry; - boost::scoped_ptr loop; - boost::scoped_ptr input; + std::unique_ptr loop; + std::unique_ptr input; - boost::scoped_ptr compositor; - boost::scoped_ptr shell; - boost::scoped_ptr xbmcWayland; + std::unique_ptr compositor; + std::unique_ptr shell; + std::unique_ptr xbmcWayland; - boost::scoped_ptr surface; - boost::scoped_ptr shellSurface; - boost::scoped_ptr openGLSurface; + std::unique_ptr surface; + std::unique_ptr shellSurface; + std::unique_ptr openGLSurface; virtual xwe::IEventQueueStrategy * CreateEventQueue() = 0; @@ -158,7 +156,7 @@ class InputEventsWestonTest : bool synchronized; void Synchronize(); - boost::scoped_ptr syncCallback; + std::unique_ptr syncCallback; TmpEnv m_waylandDisplayEnv; }; @@ -178,8 +176,8 @@ void InputEventsWestonTest::SetUp() xkbCommonLibrary.Load(); xkbContext.reset(CXKBKeymap::CreateXKBContext(xkbCommonLibrary), - boost::bind(&IDllXKBCommon::xkb_context_unref, - &xkbCommonLibrary, _1)); + std::bind(&IDllXKBCommon::xkb_context_unref, + &xkbCommonLibrary, std::placeholders::_1)); keymap.reset(new CXKBKeymap( xkbCommonLibrary, CXKBKeymap::CreateXKBKeymapFromNames(xkbCommonLibrary, @@ -285,8 +283,8 @@ void InputEventsWestonTest::WaitForSynchronize() synchronized = false; syncCallback.reset(new xw::Callback(clientLibrary, display->Sync(), - boost::bind(&InputEventsWestonTest::Synchronize, - this))); + std::bind(&InputEventsWestonTest::Synchronize, + this))); while (!synchronized) loop->Dispatch(); diff --git a/xbmc/windowing/tests/wayland/TmpEnv.h b/xbmc/windowing/tests/wayland/TmpEnv.h index 7f67af4c2fdb1..94632080e60f9 100644 --- a/xbmc/windowing/tests/wayland/TmpEnv.h +++ b/xbmc/windowing/tests/wayland/TmpEnv.h @@ -19,16 +19,17 @@ * . * */ -#include -class TmpEnv : - boost::noncopyable +class TmpEnv { public: TmpEnv(const char *env, const char *val); ~TmpEnv(); + TmpEnv(const TmpEnv &) = delete; + TmpEnv &operator=(const TmpEnv &) = delete; + private: const char *m_env; diff --git a/xbmc/windowing/tests/wayland/WestonProcess.cpp b/xbmc/windowing/tests/wayland/WestonProcess.cpp index abc5071c177b4..945c9debc5413 100644 --- a/xbmc/windowing/tests/wayland/WestonProcess.cpp +++ b/xbmc/windowing/tests/wayland/WestonProcess.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include diff --git a/xbmc/windowing/tests/wayland/WestonProcess.h b/xbmc/windowing/tests/wayland/WestonProcess.h index 6d923cf37c3a8..de9a640c781d1 100644 --- a/xbmc/windowing/tests/wayland/WestonProcess.h +++ b/xbmc/windowing/tests/wayland/WestonProcess.h @@ -21,8 +21,6 @@ */ #include "system.h" -#include - #ifdef UNICODE typedef std::wstring westring; #else @@ -35,8 +33,7 @@ namespace xbmc { namespace test { -class Process : - boost::noncopyable +class Process { public: @@ -44,6 +41,9 @@ class Process : const westring &socket); ~Process(); + Process(const Process &) = delete; + Process &operator=(const Process &) = delete; + void WaitForSignal(int signal, int timeout); void WaitForStatus(int status, int timeout); diff --git a/xbmc/windowing/tests/wayland/WestonTest.cpp b/xbmc/windowing/tests/wayland/WestonTest.cpp index d962a588983e4..22ac7755262f9 100644 --- a/xbmc/windowing/tests/wayland/WestonTest.cpp +++ b/xbmc/windowing/tests/wayland/WestonTest.cpp @@ -19,8 +19,7 @@ */ #include #include - -#include +#include #include @@ -35,13 +34,15 @@ namespace xt = xbmc::test; namespace { -class TempFileWrapper : - boost::noncopyable +class TempFileWrapper { public: TempFileWrapper(const westring &suffix); ~TempFileWrapper(); + + TempFileWrapper(const TempFileWrapper &) = delete; + TempFileWrapper &operator=(const TempFileWrapper &) = delete; void FetchDirectory(westring &directory); void FetchFilename(westring &name); @@ -75,13 +76,15 @@ void TempFileWrapper::FetchFilename(westring &name) name = path.substr(directory.size()); } -class SavedTempSocket : - boost::noncopyable +class SavedTempSocket { public: SavedTempSocket(); + SavedTempSocket(const SavedTempSocket &) = delete; + SavedTempSocket &operator=(const SavedTempSocket &) = delete; + const westring & FetchFilename(); const westring & FetchDirectory(); @@ -111,14 +114,17 @@ SavedTempSocket::FetchDirectory() } template -class SignalGuard : - boost::noncopyable +class SignalGuard { public: SignalGuard(const Iterator &begin, const Iterator &end); ~SignalGuard(); + + SignalGuard(const SignalGuard &) = delete; + SignalGuard &operator=(const SignalGuard &) = delete; + private: sigset_t mask; @@ -150,7 +156,7 @@ SignalGuard::~SignalGuard() CLog::Log(LOGERROR, "Failed to unblock signals"); } -typedef boost::array SigArray; +typedef std::array SigArray; SigArray BlockedSignals = { { diff --git a/xbmc/windowing/tests/wayland/WestonTest.h b/xbmc/windowing/tests/wayland/WestonTest.h index 5e5548c784be6..91544f5098a1b 100644 --- a/xbmc/windowing/tests/wayland/WestonTest.h +++ b/xbmc/windowing/tests/wayland/WestonTest.h @@ -19,7 +19,6 @@ * . * */ -#include #include @@ -46,5 +45,5 @@ class WestonTest : private: class Private; - boost::scoped_ptr priv; + std::unique_ptr priv; }; diff --git a/xbmc/windowing/tests/wayland/XBMCWayland.h b/xbmc/windowing/tests/wayland/XBMCWayland.h index 1a5545f89bd58..42a1651d16372 100644 --- a/xbmc/windowing/tests/wayland/XBMCWayland.h +++ b/xbmc/windowing/tests/wayland/XBMCWayland.h @@ -21,8 +21,6 @@ */ #if defined(HAVE_WAYLAND_XBMC_PROTO) -#include - struct wl_surface; struct xbmc_wayland; @@ -32,14 +30,16 @@ namespace test { namespace wayland { -class XBMCWayland : - boost::noncopyable +class XBMCWayland { public: XBMCWayland(struct xbmc_wayland *xbmcWayland); ~XBMCWayland(); + XBMCWayland(const XBMCWayland &) = delete; + XBMCWayland &operator=(const XBMCWayland &) = delete; + struct wl_surface * MostRecentSurface(); void AddMode(int width, diff --git a/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp b/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp index 90c665abccef7..a1007eee6539e 100644 --- a/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp +++ b/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp @@ -21,11 +21,7 @@ #include #include - -#include -#include -#include -#include +#include #include #include @@ -48,14 +44,17 @@ namespace test { namespace wayland { -class Listener : - boost::noncopyable +class Listener { public: - typedef boost::function Delegate; + typedef std::function Delegate; Listener(const Delegate &); + + Listener(const Listener &) = delete; + Listener &operator=(const Listener &) = delete; + void BindTo(struct wl_signal *); private: @@ -71,19 +70,21 @@ class Listener : namespace weston { -class Compositor : - boost::noncopyable +class Compositor { public: Compositor(struct weston_compositor *); ~Compositor(); + Compositor(const Compositor &) = delete; + Compositor &operator=(const Compositor &) = delete; + struct wl_display * Display(); struct weston_surface * TopSurface(); struct weston_mode * LastMode(); - void OnEachMode(const boost::function &); + void OnEachMode(const std::function &); struct wl_resource * PointerResource(struct wl_client *client); struct wl_resource * KeyboardResource(struct wl_client *client); struct weston_surface * Surface(struct wl_resource *client); @@ -104,12 +105,14 @@ class Compositor : namespace wayland { -class XBMCWayland : - boost::noncopyable +class XBMCWayland { public: ~XBMCWayland(); + + XBMCWayland(const XBMCWayland &) = delete; + XBMCWayland &operator=(const XBMCWayland &) = delete; struct wl_resource * GetResource(); @@ -400,10 +403,10 @@ xtw::XBMCWayland::AddMode(struct wl_client *client, /* Clear flags from all other outputs that may have the same flags * as this one */ - m_compositor.OnEachMode(boost::bind(ClearFlagsOnOtherModes, - _1, - flags, - &m_additionalModes.back())); + m_compositor.OnEachMode(std::bind(ClearFlagsOnOtherModes, + std::placeholders::_1, + flags, + &m_additionalModes.back())); } namespace @@ -561,7 +564,7 @@ xtwc::Compositor::Compositor(struct weston_compositor *c) : m_readySource(wl_event_loop_add_timer(wl_display_get_event_loop(Display()), Compositor::Ready, this)), - m_destroyListener(boost::bind(Compositor::Unload, this)) + m_destroyListener(std::bind(Compositor::Unload, this)) { /* Dispatch ASAP */ wl_event_source_timer_update(m_readySource, 1); @@ -683,7 +686,7 @@ xtwc::Compositor::TopSurface() } void -xtwc::Compositor::OnEachMode(const boost::function &action) +xtwc::Compositor::OnEachMode(const std::function &action) { struct weston_output *output = FirstOutput(); struct weston_mode *mode; diff --git a/xbmc/windowing/wayland/EventLoop.cpp b/xbmc/windowing/wayland/EventLoop.cpp index 5b5ea2a46d33f..6f338b5610f83 100644 --- a/xbmc/windowing/wayland/EventLoop.cpp +++ b/xbmc/windowing/wayland/EventLoop.cpp @@ -19,9 +19,7 @@ */ #include #include - -#include -#include +#include #include "utils/Stopwatch.h" @@ -40,20 +38,20 @@ namespace xwe = xbmc::wayland::events; * strategy in place. */ void xwe::Loop::OnEvent(XBMC_Event &e) { - m_eventQueue.PushAction(boost::bind(&IEventListener::OnEvent, - &m_queueListener, e)); + m_eventQueue.PushAction(std::bind(&IEventListener::OnEvent, + &m_queueListener, e)); } void xwe::Loop::OnFocused() { - m_eventQueue.PushAction(boost::bind(&IEventListener::OnFocused, - &m_queueListener)); + m_eventQueue.PushAction(std::bind(&IEventListener::OnFocused, + &m_queueListener)); } void xwe::Loop::OnUnfocused() { - m_eventQueue.PushAction(boost::bind(&IEventListener::OnUnfocused, - &m_queueListener)); + m_eventQueue.PushAction(std::bind(&IEventListener::OnUnfocused, + &m_queueListener)); } xwe::Loop::Loop(IEventListener &queueListener, @@ -110,9 +108,9 @@ void xwe::Loop::DispatchTimers() * trigger any remaining ones. If a timeout is triggered, then its * remaining time will return to the original timeout value */ std::for_each(m_callbackQueue.begin(), m_callbackQueue.end (), - boost::bind(SubtractTimeoutAndTrigger, - _1, - static_cast(elapsedMs))); + std::bind(SubtractTimeoutAndTrigger, + std::placeholders::_1, + static_cast(elapsedMs))); /* Timeout times may have changed so that the timeouts are no longer * in order. Sort them so that they are. If they are unsorted, * the ordering of two timeouts, one which was added just before diff --git a/xbmc/windowing/wayland/EventLoop.h b/xbmc/windowing/wayland/EventLoop.h index 9664358527544..eb4a73158ed21 100644 --- a/xbmc/windowing/wayland/EventLoop.h +++ b/xbmc/windowing/wayland/EventLoop.h @@ -20,8 +20,7 @@ * */ #include - -#include +#include #include "utils/Stopwatch.h" @@ -59,7 +58,7 @@ class Loop : struct CallbackTracker { - typedef boost::weak_ptr CallbackObserver; + typedef std::weak_ptr CallbackObserver; CallbackTracker(uint32_t time, uint32_t initial, diff --git a/xbmc/windowing/wayland/EventQueueStrategy.h b/xbmc/windowing/wayland/EventQueueStrategy.h index c98b3536b185c..ec12f1120d5cb 100644 --- a/xbmc/windowing/wayland/EventQueueStrategy.h +++ b/xbmc/windowing/wayland/EventQueueStrategy.h @@ -19,8 +19,7 @@ * . * */ -#include -#include +#include namespace xbmc { @@ -28,14 +27,16 @@ namespace wayland { namespace events { -class IEventQueueStrategy : - boost::noncopyable +class IEventQueueStrategy { public: - + IEventQueueStrategy() = default; virtual ~IEventQueueStrategy() {} - typedef boost::function Action; + IEventQueueStrategy(const IEventQueueStrategy &) = delete; + IEventQueueStrategy &operator=(const IEventQueueStrategy &) = delete; + + typedef std::function Action; virtual void PushAction(const Action &event) = 0; virtual void DispatchEventsFromMain() = 0; diff --git a/xbmc/windowing/wayland/InputFactory.cpp b/xbmc/windowing/wayland/InputFactory.cpp index 4d9988c176532..c0f4a47f60236 100644 --- a/xbmc/windowing/wayland/InputFactory.cpp +++ b/xbmc/windowing/wayland/InputFactory.cpp @@ -17,10 +17,6 @@ * . * */ -#include -#include -#include - #include "EventListener.h" #include "Keyboard.h" #include "Pointer.h" diff --git a/xbmc/windowing/wayland/InputFactory.h b/xbmc/windowing/wayland/InputFactory.h index 3f6d1746477d4..e46c39c991930 100644 --- a/xbmc/windowing/wayland/InputFactory.h +++ b/xbmc/windowing/wayland/InputFactory.h @@ -19,7 +19,6 @@ * . * */ -#include #include "CursorManager.h" #include "Seat.h" @@ -28,6 +27,8 @@ #include "Keyboard.h" #include "KeyboardProcessor.h" +#include + class IDllWaylandClient; class IDllXKBCommon; @@ -75,8 +76,8 @@ class InputFactory : PointerProcessor m_pointerProcessor; KeyboardProcessor m_keyboardProcessor; - boost::scoped_ptr m_seat; - boost::scoped_ptr m_pointer; - boost::scoped_ptr m_keyboard; + std::unique_ptr m_seat; + std::unique_ptr m_pointer; + std::unique_ptr m_keyboard; }; } diff --git a/xbmc/windowing/wayland/Keyboard.cpp b/xbmc/windowing/wayland/Keyboard.cpp index 1321c67a3f793..6c59da218a255 100644 --- a/xbmc/windowing/wayland/Keyboard.cpp +++ b/xbmc/windowing/wayland/Keyboard.cpp @@ -21,8 +21,6 @@ #include #include -#include -#include #include #include @@ -53,6 +51,12 @@ void DestroyXKBCommonContext(struct xkb_context *context, } } +void +xw::Keyboard::XkbContextDeleter::operator()(struct xkb_context *c) +{ + DestroyXKBCommonContext(c, m_xkbCommonLibrary); +} + xw::Keyboard::Keyboard(IDllWaylandClient &clientLibrary, IDllXKBCommon &xkbCommonLibrary, struct wl_keyboard *keyboard, @@ -60,9 +64,7 @@ xw::Keyboard::Keyboard(IDllWaylandClient &clientLibrary, m_clientLibrary(clientLibrary), m_xkbCommonLibrary(xkbCommonLibrary), m_xkbCommonContext(CXKBKeymap::CreateXKBContext(m_xkbCommonLibrary), - boost::bind(DestroyXKBCommonContext, - _1, - boost::ref(m_xkbCommonLibrary))), + XkbContextDeleter(xkbCommonLibrary)), m_keyboard(keyboard), m_reciever(receiver) { diff --git a/xbmc/windowing/wayland/Keyboard.h b/xbmc/windowing/wayland/Keyboard.h index 44cb59fafa4db..bcc65fcb3e2a9 100644 --- a/xbmc/windowing/wayland/Keyboard.h +++ b/xbmc/windowing/wayland/Keyboard.h @@ -19,12 +19,10 @@ * . * */ -#include -#include -#include - #include +#include + #include "input/linux/Keymap.h" class IDllWaylandClient; @@ -74,8 +72,7 @@ class IKeyboardReceiver * that interface should ascertain the intended keymap before processing * any other events. */ -class Keyboard : - public boost::noncopyable +class Keyboard { public: @@ -85,6 +82,9 @@ class Keyboard : IKeyboardReceiver &); ~Keyboard(); + Keyboard(const Keyboard &) = delete; + Keyboard &operator=(const Keyboard &) = delete; + struct wl_keyboard * GetWlKeyboard(); static void HandleKeymapCallback(void *, @@ -139,18 +139,24 @@ class Keyboard : IDllWaylandClient &m_clientLibrary; IDllXKBCommon &m_xkbCommonLibrary; + + struct XkbContextDeleter { + IDllXKBCommon &m_xkbCommonLibrary; + + constexpr explicit XkbContextDeleter(IDllXKBCommon &xkbCommonLibrary) + :m_xkbCommonLibrary(xkbCommonLibrary) {} + + void operator()(struct xkb_context *c); + }; - /* boost::scoped_ptr does not permit custom deleters - * and std::auto_ptr is deprecated, so we are using - * boost::shared_ptr instead */ - boost::shared_ptr m_xkbCommonContext; + std::unique_ptr m_xkbCommonContext; struct wl_keyboard *m_keyboard; IKeyboardReceiver &m_reciever; /* Keyboard owns the keymap object, but it might inject observing * references elsewhere in order to assist those objects in their * processing */ - boost::scoped_ptr m_keymap; + std::unique_ptr m_keymap; }; } } diff --git a/xbmc/windowing/wayland/KeyboardProcessor.cpp b/xbmc/windowing/wayland/KeyboardProcessor.cpp index 0f01b2efb498e..76a1380c90514 100644 --- a/xbmc/windowing/wayland/KeyboardProcessor.cpp +++ b/xbmc/windowing/wayland/KeyboardProcessor.cpp @@ -18,13 +18,7 @@ * */ #include -#include -#include - -#include -#include -#include -#include +#include #include #include @@ -165,7 +159,7 @@ xbmc::KeyboardProcessor::Key(uint32_t serial, if (keyEventType == XBMC_KEYDOWN) { m_repeatCallback = - m_timeouts.RepeatAfterMs(boost::bind ( + m_timeouts.RepeatAfterMs(std::bind ( &KeyboardProcessor::RepeatCallback, this, key, diff --git a/xbmc/windowing/wayland/KeyboardProcessor.h b/xbmc/windowing/wayland/KeyboardProcessor.h index 3a6af534456ca..1a81a95594aad 100644 --- a/xbmc/windowing/wayland/KeyboardProcessor.h +++ b/xbmc/windowing/wayland/KeyboardProcessor.h @@ -19,7 +19,6 @@ * . * */ -#include #include "input/linux/Keymap.h" #include "Keyboard.h" diff --git a/xbmc/windowing/wayland/Pointer.h b/xbmc/windowing/wayland/Pointer.h index b617d5495dac8..161580f511435 100644 --- a/xbmc/windowing/wayland/Pointer.h +++ b/xbmc/windowing/wayland/Pointer.h @@ -19,8 +19,6 @@ * . * */ -#include - #include class IDllWaylandClient; diff --git a/xbmc/windowing/wayland/PollThread.cpp b/xbmc/windowing/wayland/PollThread.cpp index 70732fc950004..e874593d1cea4 100644 --- a/xbmc/windowing/wayland/PollThread.cpp +++ b/xbmc/windowing/wayland/PollThread.cpp @@ -20,10 +20,6 @@ #include #include -#include -#include -#include - #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif @@ -31,6 +27,7 @@ #include #include #include +#include #include "utils/log.h" diff --git a/xbmc/windowing/wayland/PollThread.h b/xbmc/windowing/wayland/PollThread.h index 07ca2d2bc1448..de87990de2a0f 100644 --- a/xbmc/windowing/wayland/PollThread.h +++ b/xbmc/windowing/wayland/PollThread.h @@ -19,11 +19,10 @@ * . * */ -#include -#include - #include "threads/Thread.h" +#include + namespace xbmc { namespace wayland @@ -44,7 +43,7 @@ class PollThread : { public: - typedef boost::function Dispatch; + typedef std::function Dispatch; PollThread(const Dispatch &dispatch, const Dispatch &beforePoll, diff --git a/xbmc/windowing/wayland/Seat.h b/xbmc/windowing/wayland/Seat.h index 49ae3aad06a81..e74da006c0c86 100644 --- a/xbmc/windowing/wayland/Seat.h +++ b/xbmc/windowing/wayland/Seat.h @@ -19,8 +19,6 @@ * . * */ -#include - #include class IDllWaylandClient; @@ -42,8 +40,7 @@ class IInputReceiver virtual void RemoveKeyboard() = 0; }; -class Seat : - public boost::noncopyable +class Seat { public: @@ -52,6 +49,9 @@ class Seat : IInputReceiver &); ~Seat(); + Seat(const Seat &) = delete; + Seat &operator=(const Seat &) = delete; + struct wl_seat * GetWlSeat(); static void HandleCapabilitiesCallback(void *, diff --git a/xbmc/windowing/wayland/TimeoutManager.h b/xbmc/windowing/wayland/TimeoutManager.h index c1dea95f10de1..16cb83467eb8e 100644 --- a/xbmc/windowing/wayland/TimeoutManager.h +++ b/xbmc/windowing/wayland/TimeoutManager.h @@ -19,8 +19,8 @@ * . * */ -#include -#include +#include +#include namespace xbmc { @@ -34,8 +34,8 @@ class ITimeoutManager { public: - typedef boost::function Callback; - typedef boost::shared_ptr CallbackPtr; + typedef std::function Callback; + typedef std::shared_ptr CallbackPtr; virtual ~ITimeoutManager() {} virtual CallbackPtr RepeatAfterMs (const Callback &callback, diff --git a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp index c2bd327804f2c..b1f2078606239 100644 --- a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp +++ b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp @@ -18,10 +18,7 @@ * */ #include - -#include -#include -#include +#include #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -78,12 +75,12 @@ xw11::EventQueueStrategy::EventQueueStrategy(IDllWaylandClient &clientLibrary, struct wl_display *display) : m_clientLibrary(clientLibrary), m_display(display), - m_thread(boost::bind(ReadAndDispatch, - boost::ref(m_clientLibrary), - m_display), - boost::bind(DispatchPendingEvents, - boost::ref(m_clientLibrary), - m_display), + m_thread(std::bind(ReadAndDispatch, + std::ref(m_clientLibrary), + m_display), + std::bind(DispatchPendingEvents, + std::ref(m_clientLibrary), + m_display), m_clientLibrary.wl_display_get_fd(m_display)) { } diff --git a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h index e6c394555e46f..18914de694372 100644 --- a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h +++ b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h @@ -21,8 +21,6 @@ */ #include -#include - #include "threads/CriticalSection.h" #include "EventQueueStrategy.h" #include "PollThread.h" diff --git a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp index 93cf18cc07e36..57bafb437852b 100644 --- a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp +++ b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp @@ -17,9 +17,7 @@ * . * */ -#include -#include -#include +#include #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -56,8 +54,8 @@ xw12::EventQueueStrategy::EventQueueStrategy(IDllWaylandClient &clientLibrary, struct wl_display *display) : m_clientLibrary(clientLibrary), m_display(display), - m_thread(boost::bind(Read, boost::ref(m_clientLibrary), display), - boost::bind(Nothing), + m_thread(std::bind(Read, std::ref(m_clientLibrary), display), + std::bind(Nothing), m_clientLibrary.wl_display_get_fd(m_display)) { } diff --git a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h index 584e0117f1672..32836ff617224 100644 --- a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h +++ b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h @@ -21,8 +21,6 @@ */ #include -#include - #include "EventQueueStrategy.h" #include "PollThread.h" From e1c6fab9a9d8056c52eb34c11021659521922dd4 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 29/59] windowing/egl/wayland: move to windowing/wayland/ In https://github.com/xbmc/xbmc/pull/8980, FernetMenta postulated: "If anybody wants to re-submit wayland, it has to comply to the architecture. That is no components under the folder windowing/egl, no boost." This patch is trying to comply with this rule. Signed-off-by: memeka --- xbmc/input/linux/XKBCommonKeymap.cpp | 2 +- xbmc/windowing/WinEvents.cpp | 2 +- xbmc/windowing/egl/EGLWrapper.cpp | 2 +- .../wayland/TestEGLNativeTypeWayland.cpp | 8 +++--- .../TestXBMCWaylandInputAcceptance.cpp | 26 +++++++++---------- xbmc/windowing/{egl => }/wayland/Callback.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Callback.h | 0 .../{egl => }/wayland/Compositor.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Compositor.h | 0 xbmc/windowing/{egl => }/wayland/Display.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Display.h | 0 .../{ => wayland}/DllWaylandClient.h | 0 xbmc/windowing/{ => wayland}/DllWaylandEgl.h | 0 xbmc/windowing/{ => wayland}/DllXKBCommon.h | 0 .../{egl => wayland}/EGLNativeTypeWayland.cpp | 16 ++++++------ .../{egl => wayland}/EGLNativeTypeWayland.h | 2 +- xbmc/windowing/wayland/Keyboard.cpp | 6 ++--- .../{egl => }/wayland/OpenGLSurface.cpp | 2 +- .../{egl => }/wayland/OpenGLSurface.h | 0 xbmc/windowing/{egl => }/wayland/Output.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Output.h | 0 xbmc/windowing/wayland/Pointer.cpp | 4 +-- xbmc/windowing/wayland/PointerProcessor.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Region.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Region.h | 0 xbmc/windowing/{egl => }/wayland/Registry.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Registry.h | 2 +- xbmc/windowing/wayland/Seat.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Shell.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Shell.h | 0 .../{egl => }/wayland/ShellSurface.cpp | 4 +-- .../{egl => }/wayland/ShellSurface.h | 0 xbmc/windowing/{egl => }/wayland/Surface.cpp | 4 +-- xbmc/windowing/{egl => }/wayland/Surface.h | 0 .../wayland/Wayland11EventQueueStrategy.cpp | 2 +- .../wayland/Wayland12EventQueueStrategy.cpp | 2 +- .../{egl => }/wayland/WaylandLibraries.cpp | 0 .../{egl => }/wayland/WaylandLibraries.h | 6 ++--- .../windowing/{ => wayland}/WaylandProtocol.h | 0 .../{ => wayland}/WinEventsWayland.cpp | 6 ++--- .../{ => wayland}/WinEventsWayland.h | 0 .../{egl => }/wayland/XBMCConnection.cpp | 10 +++---- .../{egl => }/wayland/XBMCConnection.h | 0 .../{egl => }/wayland/XBMCSurface.cpp | 6 ++--- .../windowing/{egl => }/wayland/XBMCSurface.h | 0 45 files changed, 74 insertions(+), 74 deletions(-) rename xbmc/windowing/{egl => }/wayland/Callback.cpp (95%) rename xbmc/windowing/{egl => }/wayland/Callback.h (100%) rename xbmc/windowing/{egl => }/wayland/Compositor.cpp (96%) rename xbmc/windowing/{egl => }/wayland/Compositor.h (100%) rename xbmc/windowing/{egl => }/wayland/Display.cpp (97%) rename xbmc/windowing/{egl => }/wayland/Display.h (100%) rename xbmc/windowing/{ => wayland}/DllWaylandClient.h (100%) rename xbmc/windowing/{ => wayland}/DllWaylandEgl.h (100%) rename xbmc/windowing/{ => wayland}/DllXKBCommon.h (100%) rename xbmc/windowing/{egl => wayland}/EGLNativeTypeWayland.cpp (96%) rename xbmc/windowing/{egl => wayland}/EGLNativeTypeWayland.h (97%) rename xbmc/windowing/{egl => }/wayland/OpenGLSurface.cpp (97%) rename xbmc/windowing/{egl => }/wayland/OpenGLSurface.h (100%) rename xbmc/windowing/{egl => }/wayland/Output.cpp (98%) rename xbmc/windowing/{egl => }/wayland/Output.h (100%) rename xbmc/windowing/{egl => }/wayland/Region.cpp (95%) rename xbmc/windowing/{egl => }/wayland/Region.h (100%) rename xbmc/windowing/{egl => }/wayland/Registry.cpp (98%) rename xbmc/windowing/{egl => }/wayland/Registry.h (98%) rename xbmc/windowing/{egl => }/wayland/Shell.cpp (95%) rename xbmc/windowing/{egl => }/wayland/Shell.h (100%) rename xbmc/windowing/{egl => }/wayland/ShellSurface.cpp (97%) rename xbmc/windowing/{egl => }/wayland/ShellSurface.h (100%) rename xbmc/windowing/{egl => }/wayland/Surface.cpp (97%) rename xbmc/windowing/{egl => }/wayland/Surface.h (100%) rename xbmc/windowing/{egl => }/wayland/WaylandLibraries.cpp (100%) rename xbmc/windowing/{egl => }/wayland/WaylandLibraries.h (94%) rename xbmc/windowing/{ => wayland}/WaylandProtocol.h (100%) rename xbmc/windowing/{ => wayland}/WinEventsWayland.cpp (97%) rename xbmc/windowing/{ => wayland}/WinEventsWayland.h (100%) rename xbmc/windowing/{egl => }/wayland/XBMCConnection.cpp (99%) rename xbmc/windowing/{egl => }/wayland/XBMCConnection.h (100%) rename xbmc/windowing/{egl => }/wayland/XBMCSurface.cpp (98%) rename xbmc/windowing/{egl => }/wayland/XBMCSurface.h (100%) diff --git a/xbmc/input/linux/XKBCommonKeymap.cpp b/xbmc/input/linux/XKBCommonKeymap.cpp index acadf9f0261c6..79959f55f38a9 100644 --- a/xbmc/input/linux/XKBCommonKeymap.cpp +++ b/xbmc/input/linux/XKBCommonKeymap.cpp @@ -29,7 +29,7 @@ #include "Application.h" -#include "windowing/DllXKBCommon.h" +#include "windowing/wayland/DllXKBCommon.h" #include "XKBCommonKeymap.h" #include "Util.h" diff --git a/xbmc/windowing/WinEvents.cpp b/xbmc/windowing/WinEvents.cpp index 22fe2bcc401de..dafa17a6709b6 100644 --- a/xbmc/windowing/WinEvents.cpp +++ b/xbmc/windowing/WinEvents.cpp @@ -47,7 +47,7 @@ #define WinEventsType CWinEventsX11 #elif defined(HAVE_WAYLAND) -#include "WinEventsWayland.h" +#include "wayland/WinEventsWayland.h" #define WinEventsType CWinEventsWayland #elif defined(TARGET_LINUX) && defined(HAS_LINUX_EVENTS) diff --git a/xbmc/windowing/egl/EGLWrapper.cpp b/xbmc/windowing/egl/EGLWrapper.cpp index 3da8f78eee968..961d92665da74 100644 --- a/xbmc/windowing/egl/EGLWrapper.cpp +++ b/xbmc/windowing/egl/EGLWrapper.cpp @@ -23,7 +23,7 @@ #include "utils/log.h" #include #if defined(HAVE_WAYLAND) - #include "EGLNativeTypeWayland.h" + #include "windowing/wayland/EGLNativeTypeWayland.h" #endif #if defined(TARGET_ANDROID) #include "EGLNativeTypeAndroid.h" diff --git a/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp b/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp index c0c88c1bf8da0..b2d79b6787a28 100644 --- a/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp +++ b/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp @@ -34,10 +34,10 @@ #include "xbmc_wayland_test_client_protocol.h" #endif -#include "windowing/egl/wayland/Display.h" -#include "windowing/egl/wayland/Registry.h" -#include "windowing/egl/wayland/Surface.h" -#include "windowing/egl/EGLNativeTypeWayland.h" +#include "windowing/wayland/Display.h" +#include "windowing/wayland/Registry.h" +#include "windowing/wayland/Surface.h" +#include "windowing/wayland/EGLNativeTypeWayland.h" #include "TmpEnv.h" #include "WestonTest.h" diff --git a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp index 3e60565fb9cd2..7e5a98804124d 100644 --- a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp +++ b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp @@ -29,19 +29,19 @@ #include #include #include "xbmc_wayland_test_client_protocol.h" -#include "windowing/DllWaylandClient.h" -#include "windowing/DllWaylandEgl.h" -#include "windowing/DllXKBCommon.h" - -#include "windowing/egl/wayland/Callback.h" -#include "windowing/egl/wayland/Compositor.h" -#include "windowing/egl/wayland/Display.h" -#include "windowing/egl/wayland/OpenGLSurface.h" -#include "windowing/egl/wayland/Registry.h" -#include "windowing/egl/wayland/Surface.h" -#include "windowing/egl/wayland/Shell.h" -#include "windowing/egl/wayland/ShellSurface.h" -#include "windowing/egl/EGLNativeTypeWayland.h" +#include "windowing/wayland/DllWaylandClient.h" +#include "windowing/wayland/DllWaylandEgl.h" +#include "windowing/wayland/DllXKBCommon.h" + +#include "windowing/wayland/Callback.h" +#include "windowing/wayland/Compositor.h" +#include "windowing/wayland/Display.h" +#include "windowing/wayland/OpenGLSurface.h" +#include "windowing/wayland/Registry.h" +#include "windowing/wayland/Surface.h" +#include "windowing/wayland/Shell.h" +#include "windowing/wayland/ShellSurface.h" +#include "windowing/wayland/EGLNativeTypeWayland.h" #include "windowing/wayland/EventLoop.h" #include "windowing/wayland/EventQueueStrategy.h" #include "windowing/wayland/TimeoutManager.h" diff --git a/xbmc/windowing/egl/wayland/Callback.cpp b/xbmc/windowing/wayland/Callback.cpp similarity index 95% rename from xbmc/windowing/egl/wayland/Callback.cpp rename to xbmc/windowing/wayland/Callback.cpp index 0055d1780538c..a332630aca9a6 100644 --- a/xbmc/windowing/egl/wayland/Callback.cpp +++ b/xbmc/windowing/wayland/Callback.cpp @@ -19,8 +19,8 @@ */ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Callback.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Callback.h b/xbmc/windowing/wayland/Callback.h similarity index 100% rename from xbmc/windowing/egl/wayland/Callback.h rename to xbmc/windowing/wayland/Callback.h diff --git a/xbmc/windowing/egl/wayland/Compositor.cpp b/xbmc/windowing/wayland/Compositor.cpp similarity index 96% rename from xbmc/windowing/egl/wayland/Compositor.cpp rename to xbmc/windowing/wayland/Compositor.cpp index df0f52e5b9ae6..f7a1b1e9905b3 100644 --- a/xbmc/windowing/egl/wayland/Compositor.cpp +++ b/xbmc/windowing/wayland/Compositor.cpp @@ -19,8 +19,8 @@ */ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Compositor.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Compositor.h b/xbmc/windowing/wayland/Compositor.h similarity index 100% rename from xbmc/windowing/egl/wayland/Compositor.h rename to xbmc/windowing/wayland/Compositor.h diff --git a/xbmc/windowing/egl/wayland/Display.cpp b/xbmc/windowing/wayland/Display.cpp similarity index 97% rename from xbmc/windowing/egl/wayland/Display.cpp rename to xbmc/windowing/wayland/Display.cpp index bd6076a6ba3c3..6e59db550219c 100644 --- a/xbmc/windowing/egl/wayland/Display.cpp +++ b/xbmc/windowing/wayland/Display.cpp @@ -25,8 +25,8 @@ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Display.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Display.h b/xbmc/windowing/wayland/Display.h similarity index 100% rename from xbmc/windowing/egl/wayland/Display.h rename to xbmc/windowing/wayland/Display.h diff --git a/xbmc/windowing/DllWaylandClient.h b/xbmc/windowing/wayland/DllWaylandClient.h similarity index 100% rename from xbmc/windowing/DllWaylandClient.h rename to xbmc/windowing/wayland/DllWaylandClient.h diff --git a/xbmc/windowing/DllWaylandEgl.h b/xbmc/windowing/wayland/DllWaylandEgl.h similarity index 100% rename from xbmc/windowing/DllWaylandEgl.h rename to xbmc/windowing/wayland/DllWaylandEgl.h diff --git a/xbmc/windowing/DllXKBCommon.h b/xbmc/windowing/wayland/DllXKBCommon.h similarity index 100% rename from xbmc/windowing/DllXKBCommon.h rename to xbmc/windowing/wayland/DllXKBCommon.h diff --git a/xbmc/windowing/egl/EGLNativeTypeWayland.cpp b/xbmc/windowing/wayland/EGLNativeTypeWayland.cpp similarity index 96% rename from xbmc/windowing/egl/EGLNativeTypeWayland.cpp rename to xbmc/windowing/wayland/EGLNativeTypeWayland.cpp index 06a3188b2dd60..ab9000cbc82b5 100644 --- a/xbmc/windowing/egl/EGLNativeTypeWayland.cpp +++ b/xbmc/windowing/wayland/EGLNativeTypeWayland.cpp @@ -32,19 +32,19 @@ #include #include -#include "windowing/DllWaylandClient.h" -#include "windowing/DllWaylandEgl.h" -#include "windowing/DllXKBCommon.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "DllWaylandEgl.h" +#include "DllXKBCommon.h" +#include "WaylandProtocol.h" #include "guilib/gui3d.h" #include "utils/log.h" #include "windowing/WinEvents.h" -#include "windowing/WinEventsWayland.h" +#include "WinEventsWayland.h" -#include "wayland/WaylandLibraries.h" -#include "wayland/XBMCConnection.h" -#include "wayland/XBMCSurface.h" +#include "WaylandLibraries.h" +#include "XBMCConnection.h" +#include "XBMCSurface.h" #endif diff --git a/xbmc/windowing/egl/EGLNativeTypeWayland.h b/xbmc/windowing/wayland/EGLNativeTypeWayland.h similarity index 97% rename from xbmc/windowing/egl/EGLNativeTypeWayland.h rename to xbmc/windowing/wayland/EGLNativeTypeWayland.h index fd45c6a1d8e20..5a1a57d41137b 100644 --- a/xbmc/windowing/egl/EGLNativeTypeWayland.h +++ b/xbmc/windowing/wayland/EGLNativeTypeWayland.h @@ -21,7 +21,7 @@ */ #include "system_egl.h" -#include "EGLNativeType.h" +#include "windowing/egl/EGLNativeType.h" #include diff --git a/xbmc/windowing/wayland/Keyboard.cpp b/xbmc/windowing/wayland/Keyboard.cpp index 6c59da218a255..1ed76c0b549fc 100644 --- a/xbmc/windowing/wayland/Keyboard.cpp +++ b/xbmc/windowing/wayland/Keyboard.cpp @@ -25,9 +25,9 @@ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/DllXKBCommon.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "DllXKBCommon.h" +#include "WaylandProtocol.h" #include "input/linux/XKBCommonKeymap.h" #include "Keyboard.h" diff --git a/xbmc/windowing/egl/wayland/OpenGLSurface.cpp b/xbmc/windowing/wayland/OpenGLSurface.cpp similarity index 97% rename from xbmc/windowing/egl/wayland/OpenGLSurface.cpp rename to xbmc/windowing/wayland/OpenGLSurface.cpp index 551c1df48ff76..2aac14a049e63 100644 --- a/xbmc/windowing/egl/wayland/OpenGLSurface.cpp +++ b/xbmc/windowing/wayland/OpenGLSurface.cpp @@ -20,7 +20,7 @@ #include #include -#include "windowing/DllWaylandEgl.h" +#include "DllWaylandEgl.h" #include "OpenGLSurface.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/OpenGLSurface.h b/xbmc/windowing/wayland/OpenGLSurface.h similarity index 100% rename from xbmc/windowing/egl/wayland/OpenGLSurface.h rename to xbmc/windowing/wayland/OpenGLSurface.h diff --git a/xbmc/windowing/egl/wayland/Output.cpp b/xbmc/windowing/wayland/Output.cpp similarity index 98% rename from xbmc/windowing/egl/wayland/Output.cpp rename to xbmc/windowing/wayland/Output.cpp index 56bbd3b6cb526..14cb8c75a906c 100644 --- a/xbmc/windowing/egl/wayland/Output.cpp +++ b/xbmc/windowing/wayland/Output.cpp @@ -23,8 +23,8 @@ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Output.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Output.h b/xbmc/windowing/wayland/Output.h similarity index 100% rename from xbmc/windowing/egl/wayland/Output.h rename to xbmc/windowing/wayland/Output.h diff --git a/xbmc/windowing/wayland/Pointer.cpp b/xbmc/windowing/wayland/Pointer.cpp index b66e4a9a7ba64..1422be698f47e 100644 --- a/xbmc/windowing/wayland/Pointer.cpp +++ b/xbmc/windowing/wayland/Pointer.cpp @@ -23,8 +23,8 @@ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Pointer.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/wayland/PointerProcessor.cpp b/xbmc/windowing/wayland/PointerProcessor.cpp index 20abab6d4f763..ea8c7449b2ecb 100644 --- a/xbmc/windowing/wayland/PointerProcessor.cpp +++ b/xbmc/windowing/wayland/PointerProcessor.cpp @@ -20,8 +20,8 @@ #include #include -#include "windowing/DllWaylandClient.h" -#include "windowing/DllXKBCommon.h" +#include "DllWaylandClient.h" +#include "DllXKBCommon.h" #include "CursorManager.h" #include "EventListener.h" diff --git a/xbmc/windowing/egl/wayland/Region.cpp b/xbmc/windowing/wayland/Region.cpp similarity index 95% rename from xbmc/windowing/egl/wayland/Region.cpp rename to xbmc/windowing/wayland/Region.cpp index 62aed1b601206..e77ec0ec308b5 100644 --- a/xbmc/windowing/egl/wayland/Region.cpp +++ b/xbmc/windowing/wayland/Region.cpp @@ -19,8 +19,8 @@ */ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Region.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Region.h b/xbmc/windowing/wayland/Region.h similarity index 100% rename from xbmc/windowing/egl/wayland/Region.h rename to xbmc/windowing/wayland/Region.h diff --git a/xbmc/windowing/egl/wayland/Registry.cpp b/xbmc/windowing/wayland/Registry.cpp similarity index 98% rename from xbmc/windowing/egl/wayland/Registry.cpp rename to xbmc/windowing/wayland/Registry.cpp index 322d883df07d8..07869aac37e5e 100644 --- a/xbmc/windowing/egl/wayland/Registry.cpp +++ b/xbmc/windowing/wayland/Registry.cpp @@ -19,8 +19,8 @@ */ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Registry.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Registry.h b/xbmc/windowing/wayland/Registry.h similarity index 98% rename from xbmc/windowing/egl/wayland/Registry.h rename to xbmc/windowing/wayland/Registry.h index 8af1a855a302e..53f0275f4081d 100644 --- a/xbmc/windowing/egl/wayland/Registry.h +++ b/xbmc/windowing/wayland/Registry.h @@ -25,7 +25,7 @@ #include -#include "windowing/WaylandProtocol.h" +#include "WaylandProtocol.h" class IDllWaylandClient; diff --git a/xbmc/windowing/wayland/Seat.cpp b/xbmc/windowing/wayland/Seat.cpp index fbd11c47abeec..5580ac8137347 100644 --- a/xbmc/windowing/wayland/Seat.cpp +++ b/xbmc/windowing/wayland/Seat.cpp @@ -23,8 +23,8 @@ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Seat.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Shell.cpp b/xbmc/windowing/wayland/Shell.cpp similarity index 95% rename from xbmc/windowing/egl/wayland/Shell.cpp rename to xbmc/windowing/wayland/Shell.cpp index cdc9bad09ab7c..9655f0d9a818b 100644 --- a/xbmc/windowing/egl/wayland/Shell.cpp +++ b/xbmc/windowing/wayland/Shell.cpp @@ -19,8 +19,8 @@ */ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Shell.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Shell.h b/xbmc/windowing/wayland/Shell.h similarity index 100% rename from xbmc/windowing/egl/wayland/Shell.h rename to xbmc/windowing/wayland/Shell.h diff --git a/xbmc/windowing/egl/wayland/ShellSurface.cpp b/xbmc/windowing/wayland/ShellSurface.cpp similarity index 97% rename from xbmc/windowing/egl/wayland/ShellSurface.cpp rename to xbmc/windowing/wayland/ShellSurface.cpp index a4070c8e23b2d..979d8025a73e3 100644 --- a/xbmc/windowing/egl/wayland/ShellSurface.cpp +++ b/xbmc/windowing/wayland/ShellSurface.cpp @@ -19,8 +19,8 @@ */ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "ShellSurface.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/ShellSurface.h b/xbmc/windowing/wayland/ShellSurface.h similarity index 100% rename from xbmc/windowing/egl/wayland/ShellSurface.h rename to xbmc/windowing/wayland/ShellSurface.h diff --git a/xbmc/windowing/egl/wayland/Surface.cpp b/xbmc/windowing/wayland/Surface.cpp similarity index 97% rename from xbmc/windowing/egl/wayland/Surface.cpp rename to xbmc/windowing/wayland/Surface.cpp index 9082d3032bb47..18933b2bb556e 100644 --- a/xbmc/windowing/egl/wayland/Surface.cpp +++ b/xbmc/windowing/wayland/Surface.cpp @@ -19,8 +19,8 @@ */ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/WaylandProtocol.h" +#include "DllWaylandClient.h" +#include "WaylandProtocol.h" #include "Surface.h" namespace xw = xbmc::wayland; diff --git a/xbmc/windowing/egl/wayland/Surface.h b/xbmc/windowing/wayland/Surface.h similarity index 100% rename from xbmc/windowing/egl/wayland/Surface.h rename to xbmc/windowing/wayland/Surface.h diff --git a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp index b1f2078606239..a2700e09195c9 100644 --- a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp +++ b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp @@ -24,7 +24,7 @@ #define _GNU_SOURCE #endif -#include "windowing/DllWaylandClient.h" +#include "DllWaylandClient.h" #include "utils/log.h" #include "Wayland11EventQueueStrategy.h" diff --git a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp index 57bafb437852b..9415527f5e4f4 100644 --- a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp +++ b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp @@ -23,7 +23,7 @@ #define _GNU_SOURCE #endif -#include "windowing/DllWaylandClient.h" +#include "DllWaylandClient.h" #include "utils/log.h" #include "Wayland12EventQueueStrategy.h" diff --git a/xbmc/windowing/egl/wayland/WaylandLibraries.cpp b/xbmc/windowing/wayland/WaylandLibraries.cpp similarity index 100% rename from xbmc/windowing/egl/wayland/WaylandLibraries.cpp rename to xbmc/windowing/wayland/WaylandLibraries.cpp diff --git a/xbmc/windowing/egl/wayland/WaylandLibraries.h b/xbmc/windowing/wayland/WaylandLibraries.h similarity index 94% rename from xbmc/windowing/egl/wayland/WaylandLibraries.h rename to xbmc/windowing/wayland/WaylandLibraries.h index d4ac7ee299b18..8b6ea52e61f77 100644 --- a/xbmc/windowing/egl/wayland/WaylandLibraries.h +++ b/xbmc/windowing/wayland/WaylandLibraries.h @@ -19,9 +19,9 @@ * . * */ -#include "windowing/DllWaylandClient.h" -#include "windowing/DllWaylandEgl.h" -#include "windowing/DllXKBCommon.h" +#include "DllWaylandClient.h" +#include "DllWaylandEgl.h" +#include "DllXKBCommon.h" namespace xbmc { diff --git a/xbmc/windowing/WaylandProtocol.h b/xbmc/windowing/wayland/WaylandProtocol.h similarity index 100% rename from xbmc/windowing/WaylandProtocol.h rename to xbmc/windowing/wayland/WaylandProtocol.h diff --git a/xbmc/windowing/WinEventsWayland.cpp b/xbmc/windowing/wayland/WinEventsWayland.cpp similarity index 97% rename from xbmc/windowing/WinEventsWayland.cpp rename to xbmc/windowing/wayland/WinEventsWayland.cpp index 6913be664c5b6..dc2e8d06e04b9 100644 --- a/xbmc/windowing/WinEventsWayland.cpp +++ b/xbmc/windowing/wayland/WinEventsWayland.cpp @@ -25,9 +25,9 @@ #include "xbmc/windowing/WindowingFactory.h" #include "WinEventsWayland.h" -#include "wayland/EventListener.h" -#include "wayland/InputFactory.h" -#include "wayland/EventLoop.h" +#include "EventListener.h" +#include "InputFactory.h" +#include "EventLoop.h" #include diff --git a/xbmc/windowing/WinEventsWayland.h b/xbmc/windowing/wayland/WinEventsWayland.h similarity index 100% rename from xbmc/windowing/WinEventsWayland.h rename to xbmc/windowing/wayland/WinEventsWayland.h diff --git a/xbmc/windowing/egl/wayland/XBMCConnection.cpp b/xbmc/windowing/wayland/XBMCConnection.cpp similarity index 99% rename from xbmc/windowing/egl/wayland/XBMCConnection.cpp rename to xbmc/windowing/wayland/XBMCConnection.cpp index a6b823a2b8106..46960fc71330c 100644 --- a/xbmc/windowing/egl/wayland/XBMCConnection.cpp +++ b/xbmc/windowing/wayland/XBMCConnection.cpp @@ -31,8 +31,8 @@ #include "utils/StringUtils.h" -#include "windowing/DllWaylandClient.h" -#include "windowing/DllXKBCommon.h" +#include "DllWaylandClient.h" +#include "DllXKBCommon.h" #include "Callback.h" #include "Compositor.h" @@ -42,11 +42,11 @@ #include "Region.h" #include "Shell.h" -#include "windowing/WaylandProtocol.h" +#include "WaylandProtocol.h" #include "XBMCConnection.h" -#include "windowing/wayland/Wayland11EventQueueStrategy.h" -#include "windowing/wayland/Wayland12EventQueueStrategy.h" +#include "Wayland11EventQueueStrategy.h" +#include "Wayland12EventQueueStrategy.h" namespace xbmc { diff --git a/xbmc/windowing/egl/wayland/XBMCConnection.h b/xbmc/windowing/wayland/XBMCConnection.h similarity index 100% rename from xbmc/windowing/egl/wayland/XBMCConnection.h rename to xbmc/windowing/wayland/XBMCConnection.h diff --git a/xbmc/windowing/egl/wayland/XBMCSurface.cpp b/xbmc/windowing/wayland/XBMCSurface.cpp similarity index 98% rename from xbmc/windowing/egl/wayland/XBMCSurface.cpp rename to xbmc/windowing/wayland/XBMCSurface.cpp index cdcab3ddaa1c7..acfbbb7f43ae8 100644 --- a/xbmc/windowing/egl/wayland/XBMCSurface.cpp +++ b/xbmc/windowing/wayland/XBMCSurface.cpp @@ -24,8 +24,8 @@ #include -#include "windowing/DllWaylandClient.h" -#include "windowing/DllWaylandEgl.h" +#include "DllWaylandClient.h" +#include "DllWaylandEgl.h" #include "Callback.h" #include "Compositor.h" @@ -36,7 +36,7 @@ #include "ShellSurface.h" #include "Surface.h" -#include "windowing/WaylandProtocol.h" +#include "WaylandProtocol.h" #include "XBMCSurface.h" namespace xbmc diff --git a/xbmc/windowing/egl/wayland/XBMCSurface.h b/xbmc/windowing/wayland/XBMCSurface.h similarity index 100% rename from xbmc/windowing/egl/wayland/XBMCSurface.h rename to xbmc/windowing/wayland/XBMCSurface.h From 8e7bfb4ab16b6142543fdfa16b40efcabbaaaad1 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 30/59] windowing/wayland/tests/Makefile.in: rename SRCS to GENERATED for out-of-tree builds Signed-off-by: memeka --- xbmc/windowing/tests/wayland/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/windowing/tests/wayland/Makefile.in b/xbmc/windowing/tests/wayland/Makefile.in index 5c1690b02666e..dc286d0b86069 100644 --- a/xbmc/windowing/tests/wayland/Makefile.in +++ b/xbmc/windowing/tests/wayland/Makefile.in @@ -20,7 +20,7 @@ INCLUDES += -I@abs_top_srcdir@/lib/gtest/include -I@WAYLAND_TEST_INCLUDES@ LIB = test_wayland.a ifneq (,@WAYLAND_SCANNER@) -SRCS += $(WAYLAND_TEST_MODULE_PROTOCOL_SRCS) +GENERATED += $(WAYLAND_TEST_MODULE_PROTOCOL_SRCS) endif CLEAN_FILES += $(WAYLAND_TEST_MODULE_PROTOCOL_GENERATED_SRCS) xbmc-wayland-test-extension.so From d717cb3629cd43e98bfe1471a50d1feb206bb71c Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 31/59] windowing/test/wayland: fix stringstream< --- xbmc/windowing/tests/wayland/WestonProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/windowing/tests/wayland/WestonProcess.cpp b/xbmc/windowing/tests/wayland/WestonProcess.cpp index 945c9debc5413..a230553955965 100644 --- a/xbmc/windowing/tests/wayland/WestonProcess.cpp +++ b/xbmc/windowing/tests/wayland/WestonProcess.cpp @@ -556,7 +556,7 @@ xt::Process::~Process() ss << "Failed to terminate " << m_pid << std::endl; - ss << processStatusMessages; + ss << processStatusMessages.str(); throw std::runtime_error(ss.str()); } } From 34e55570c3555b5583c305bd7f42746b7687fbb9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 32/59] windowing/test/wayland: eliminate boost::tokenizer Requested on https://github.com/xbmc/xbmc/pull/8980 Signed-off-by: memeka --- .../windowing/tests/wayland/WestonProcess.cpp | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/xbmc/windowing/tests/wayland/WestonProcess.cpp b/xbmc/windowing/tests/wayland/WestonProcess.cpp index a230553955965..e40527ad36829 100644 --- a/xbmc/windowing/tests/wayland/WestonProcess.cpp +++ b/xbmc/windowing/tests/wayland/WestonProcess.cpp @@ -19,9 +19,9 @@ */ #include #include +#include -#include - +#include #include #include @@ -34,6 +34,35 @@ namespace xt = xbmc::test; +template +static void +SplitForEach(const char *p, char separator, F &&f) +{ + while (true) { + const char *q = strchr(p, separator); + if (q == nullptr) { + if (*p != 0) + f(p); + break; + } + + if (q > p) + f(std::string(p, q).c_str()); + + p = q + 1; + } +} + +static std::list +Split(const char *p, char separator) +{ + std::list list; + + SplitForEach(p, separator, [&list](const char *token){ + list.push_back(token); + }); +} + namespace { std::string @@ -42,21 +71,10 @@ FindBinaryFromPATH(const std::string &binary) const char *pathEnvironmentCArray = getenv("PATH"); if (!pathEnvironmentCArray) throw std::runtime_error("PATH is not set"); - - std::string pathEnvironment(pathEnvironmentCArray); - - typedef boost::char_separator CharSeparator; - typedef boost::tokenizer CharTokenizer; - CharTokenizer paths(pathEnvironment, - CharSeparator(":")); - - for (CharTokenizer::iterator it = paths.begin(); - it != paths.end(); - ++it) - { + for (const auto &path : Split(pathEnvironmentCArray, ':')) { std::stringstream possibleBinaryLocationStream; - possibleBinaryLocationStream << *it + possibleBinaryLocationStream << path << "/" << binary; std::string possibleBinaryLocation(possibleBinaryLocationStream.str()); From 7caff1a9645847f9b498e87152a0243a5e3fdd3a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 33/59] input/XKBCommonKeymap: include cleanup Signed-off-by: memeka --- xbmc/input/linux/XKBCommonKeymap.h | 1 - 1 file changed, 1 deletion(-) diff --git a/xbmc/input/linux/XKBCommonKeymap.h b/xbmc/input/linux/XKBCommonKeymap.h index fbd6e33518519..d5fff4687da48 100644 --- a/xbmc/input/linux/XKBCommonKeymap.h +++ b/xbmc/input/linux/XKBCommonKeymap.h @@ -19,7 +19,6 @@ * . * */ -#include #include "input/linux/Keymap.h" From 90e10738ab293b533a718f49d75f677beaeecf52 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 34/59] wayland/Keyboard, input/XKBCommonKeymap: eliminate boost::scope_exit Replace with light reimplementation, with no dependencies. Boost removal was requested on https://github.com/xbmc/xbmc/pull/8980 Fixes https://github.com/MaxKellermann/xbmc/issues/3 Signed-off-by: memeka --- xbmc/input/linux/XKBCommonKeymap.cpp | 6 +- xbmc/utils/ScopeExit.hxx | 87 ++++++++++++++++++++++++++++ xbmc/windowing/wayland/Keyboard.cpp | 14 ++--- 3 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 xbmc/utils/ScopeExit.hxx diff --git a/xbmc/input/linux/XKBCommonKeymap.cpp b/xbmc/input/linux/XKBCommonKeymap.cpp index 79959f55f38a9..d9f42f195163e 100644 --- a/xbmc/input/linux/XKBCommonKeymap.cpp +++ b/xbmc/input/linux/XKBCommonKeymap.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include "utils/ScopeExit.hxx" #include @@ -85,11 +85,11 @@ CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(IDllXKBCommon &xkbCommonLibrary, st /* In every exit path, the keymap string memory region must be * unmapped */ - BOOST_SCOPE_EXIT((keymapString)(size)) + AtScopeExit(keymapString, size) { munmap(const_cast(static_cast(keymapString)), size); - } BOOST_SCOPE_EXIT_END + }; enum xkb_keymap_compile_flags flags = static_cast(0); diff --git a/xbmc/utils/ScopeExit.hxx b/xbmc/utils/ScopeExit.hxx new file mode 100644 index 0000000000000..c6c9d9cc82d73 --- /dev/null +++ b/xbmc/utils/ScopeExit.hxx @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2015 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SCOPE_EXIT_HXX +#define SCOPE_EXIT_HXX + +#include + +/** + * Internal class. Do not use directly. + */ +template +class ScopeExitGuard : F { + bool enabled = true; + +public: + explicit ScopeExitGuard(F &&f):F(std::forward(f)) {} + + ScopeExitGuard(ScopeExitGuard &&src) + :F(std::move(src)) { + src.enabled = false; + } + + ~ScopeExitGuard() { + if (enabled) + F::operator()(); + } + + ScopeExitGuard(const ScopeExitGuard &) = delete; + ScopeExitGuard &operator=(const ScopeExitGuard &) = delete; +}; + +/** + * Internal class. Do not use directly. + */ +struct ScopeExitTag { + /* this operator is a trick so we don't need to close + parantheses at the end of the expression AtScopeExit() + call */ + template + ScopeExitGuard operator+(F &&f) { + return ScopeExitGuard(std::forward(f)); + } +}; + +#define ScopeExitCat(a, b) a ## b +#define ScopeExitName(line) ScopeExitCat(at_scope_exit_, line) + +/** + * Call the block after this macro at the end of the current scope. + * Parameters are lambda captures. + * + * This is exception-safe, however the given code block must not throw + * exceptions. + * + * This attempts to be a better boost/scope_exit.hpp, without all of + * Boost's compile-time and runtime bloat. + */ +#define AtScopeExit(...) auto ScopeExitName(__LINE__) = ScopeExitTag() + [__VA_ARGS__]() + +#endif diff --git a/xbmc/windowing/wayland/Keyboard.cpp b/xbmc/windowing/wayland/Keyboard.cpp index 1ed76c0b549fc..1580640d907f3 100644 --- a/xbmc/windowing/wayland/Keyboard.cpp +++ b/xbmc/windowing/wayland/Keyboard.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include "utils/ScopeExit.hxx" #include @@ -152,10 +152,9 @@ void xw::Keyboard::HandleKeymap(uint32_t format, uint32_t size) { /* The file descriptor must always be closed */ - BOOST_SCOPE_EXIT((fd)) - { + AtScopeExit(fd) { close(fd); - } BOOST_SCOPE_EXIT_END + }; /* We don't understand anything other than xkbv1. If we get some * other keyboard, then we can't process keyboard events reliably @@ -172,11 +171,12 @@ void xw::Keyboard::HandleKeymap(uint32_t format, fd, size); - BOOST_SCOPE_EXIT((&m_xkbCommonLibrary)(&successfullyCreatedKeyboard)(keymap)) + auto &xkbCommonLibrary = m_xkbCommonLibrary; + AtScopeExit(&xkbCommonLibrary, &successfullyCreatedKeyboard, keymap) { if (!successfullyCreatedKeyboard) - m_xkbCommonLibrary.xkb_keymap_unref(keymap); - } BOOST_SCOPE_EXIT_END + xkbCommonLibrary.xkb_keymap_unref(keymap); + }; m_keymap.reset(new CXKBKeymap(m_xkbCommonLibrary, keymap)); From bc4d9b47e5de8b2c0ae9fe5671e35d4d740f1758 Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 35/59] wayland: Make sure to return the list from Split Signed-off-by: memeka --- xbmc/windowing/tests/wayland/WestonProcess.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xbmc/windowing/tests/wayland/WestonProcess.cpp b/xbmc/windowing/tests/wayland/WestonProcess.cpp index e40527ad36829..1fba0cd8e36be 100644 --- a/xbmc/windowing/tests/wayland/WestonProcess.cpp +++ b/xbmc/windowing/tests/wayland/WestonProcess.cpp @@ -60,7 +60,9 @@ Split(const char *p, char separator) SplitForEach(p, separator, [&list](const char *token){ list.push_back(token); - }); + }); + + return list; } namespace From 73be802da8ca763c56e94c51355061a432d44c9b Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:07 +0200 Subject: [PATCH 36/59] wayland: Move SplitForEach and Split to anonymous namespace Its essentially the same thing as static Signed-off-by: memeka --- xbmc/windowing/tests/wayland/WestonProcess.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xbmc/windowing/tests/wayland/WestonProcess.cpp b/xbmc/windowing/tests/wayland/WestonProcess.cpp index 1fba0cd8e36be..76d9646dfbc3c 100644 --- a/xbmc/windowing/tests/wayland/WestonProcess.cpp +++ b/xbmc/windowing/tests/wayland/WestonProcess.cpp @@ -34,8 +34,10 @@ namespace xt = xbmc::test; +namespace +{ template -static void +void SplitForEach(const char *p, char separator, F &&f) { while (true) { @@ -53,7 +55,7 @@ SplitForEach(const char *p, char separator, F &&f) } } -static std::list +std::list Split(const char *p, char separator) { std::list list; @@ -65,8 +67,6 @@ Split(const char *p, char separator) return list; } -namespace -{ std::string FindBinaryFromPATH(const std::string &binary) { From 110a5b909ec537f35305152930c5152c0181a475 Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 37/59] wayland: Don't go from char to string to char to string and back again Signed-off-by: memeka --- xbmc/windowing/tests/wayland/WestonProcess.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbmc/windowing/tests/wayland/WestonProcess.cpp b/xbmc/windowing/tests/wayland/WestonProcess.cpp index 76d9646dfbc3c..f9259229da2bb 100644 --- a/xbmc/windowing/tests/wayland/WestonProcess.cpp +++ b/xbmc/windowing/tests/wayland/WestonProcess.cpp @@ -49,7 +49,7 @@ SplitForEach(const char *p, char separator, F &&f) } if (q > p) - f(std::string(p, q).c_str()); + f(std::string(p, q)); p = q + 1; } @@ -60,7 +60,7 @@ Split(const char *p, char separator) { std::list list; - SplitForEach(p, separator, [&list](const char *token){ + SplitForEach(p, separator, [&list](std::string const &token){ list.push_back(token); }); From 9b6d3f7b9d5a5c40e1fbbdfe7749e4cb3fa10d1a Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 38/59] wayland: WAYLAND_TEST_LIBS comes from AC_SUBST, not the Makefile Use the substitution syntax. Signed-off-by: memeka --- xbmc/windowing/tests/wayland/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/windowing/tests/wayland/Makefile.in b/xbmc/windowing/tests/wayland/Makefile.in index dc286d0b86069..655e3da883e5f 100644 --- a/xbmc/windowing/tests/wayland/Makefile.in +++ b/xbmc/windowing/tests/wayland/Makefile.in @@ -44,7 +44,7 @@ xbmc_wayland_test_client_protocol.h: $(WAYLAND_TEST_MODULE_PROTOCOL) ifeq (@USE_WAYLAND_TEST_EXTENSION@,1) xbmc-wayland-test-extension.so: $(WAYLAND_TEST_MODULE_PROTOCOL_SRCS:.c=.o) $(WAYLAND_TEST_MODULE_SRCS:.cpp=.o) - $(SILENT_LD) $(CXX) $(CXXFLAGS) $(LDFLAGS) $(WAYLAND_TEST_LIBS) -shared -o $@ $+ -rdynamic + $(SILENT_LD) $(CXX) $(CXXFLAGS) $(LDFLAGS) @WAYLAND_TEST_LIBS@ -shared -o $@ $+ -rdynamic endif endif From 99b0ac3c991eddbbc2c601604baf86ea2f93d8bd Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 39/59] wayland: Don't build tests requiring module if module is not built Signed-off-by: memeka --- .../tests/wayland/TestXBMCWaylandInputAcceptance.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp index 7e5a98804124d..e7711599ce690 100644 --- a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp +++ b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp @@ -62,6 +62,8 @@ #define WAYLAND_VERSION_NUMBER ((WAYLAND_VERSION_MAJOR << 16) | (WAYLAND_VERSION_MINOR << 8) | (WAYLAND_VERSION_MICRO)) #define WAYLAND_VERSION_CHECK(major, minor, micro) ((major << 16) | (minor << 8) | (micro)) +#if defined(HAVE_WAYLAND_XBMC_PROTO) + namespace xw = xbmc::wayland; namespace xtw = xbmc::test::wayland; namespace xwe = xbmc::wayland::events; @@ -577,3 +579,5 @@ typedef ::testing::Types Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 40/59] wayland: Ensure that thread is synchronized before shutting down Signed-off-by: memeka --- .../tests/wayland/TestXBMCWaylandInputAcceptance.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp index e7711599ce690..65ce99b55108a 100644 --- a/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp +++ b/xbmc/windowing/tests/wayland/TestXBMCWaylandInputAcceptance.cpp @@ -115,6 +115,7 @@ class InputEventsWestonTest : InputEventsWestonTest(); virtual void SetUp(); + virtual void TearDown(); protected: @@ -222,6 +223,11 @@ void InputEventsWestonTest::SetUp() surface->Commit(); } +void InputEventsWestonTest::TearDown() +{ + WaitForSynchronize(); +} + bool InputEventsWestonTest::OnGlobalInterfaceAvailable(uint32_t name, const char *interface, uint32_t version) From 5494153228e61de1168f3689028456ad147e5182 Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 41/59] wayland: Make a note that initial pointer position is undefined Signed-off-by: memeka --- xbmc/windowing/wayland/PointerProcessor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/windowing/wayland/PointerProcessor.cpp b/xbmc/windowing/wayland/PointerProcessor.cpp index ea8c7449b2ecb..b64e9b247e96f 100644 --- a/xbmc/windowing/wayland/PointerProcessor.cpp +++ b/xbmc/windowing/wayland/PointerProcessor.cpp @@ -34,6 +34,7 @@ xbmc::PointerProcessor::PointerProcessor(IEventListener &listener, m_listener(listener), m_cursorManager(manager) { + /* XXX: Need to set m_lastPointerX and m_lastPointerY */ } void xbmc::PointerProcessor::Motion(uint32_t time, From 45377e3905dd9706138066b0cc4eca0ef5154520 Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 42/59] wayland: Don't include wayland-test-ext stuff if we can't compile it Signed-off-by: memeka --- xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp b/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp index b2d79b6787a28..2c5c7cfee18b9 100644 --- a/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp +++ b/xbmc/windowing/tests/wayland/TestEGLNativeTypeWayland.cpp @@ -41,14 +41,15 @@ #include "TmpEnv.h" #include "WestonTest.h" + +#if defined(HAVE_WAYLAND_XBMC_PROTO) #include "XBMCWayland.h" +#endif using ::testing::Values; using ::testing::WithParamInterface; -namespace xt = xbmc::test; namespace xw = xbmc::wayland; -namespace xtw = xbmc::test::wayland; class EGLNativeTypeWaylandWestonTest : public WestonTest @@ -191,6 +192,8 @@ TEST_F(ConnectedEGLNativeTypeWaylandWestonTest, GetMostRecentSurface) #if defined(HAVE_WAYLAND_XBMC_PROTO) +namespace xtw = xbmc::test::wayland; + class AssistedEGLNativeTypeWaylandTest : public ConnectedEGLNativeTypeWaylandWestonTest { From 6457fd5c6c0293a7d9980e0a6af3af7380111f2f Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 43/59] wayland: Get user-data through container_of There is some dark magic that goes on here. Essentially, container_of uses offsetof in order to get the struct that contained the listener. However, it only works with structs, so we have to have an inner struct for the listener and the this pointer and then an outer class which contains the inner struct. Signed-off-by: memeka --- .../tests/wayland/XBMCWaylandTestExtension.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp b/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp index a1007eee6539e..bfefb5587ed11 100644 --- a/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp +++ b/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp @@ -63,7 +63,11 @@ class Listener void Callback(); - struct wl_listener m_listener; + struct Internal { + struct wl_listener m_listener; + Listener *m_self_ptr; + } m_internal; + Delegate m_delegate; }; } @@ -535,13 +539,14 @@ xtw::XBMCWayland::PingSurface(struct wl_client *client, xtw::Listener::Listener(const Delegate &delegate) : m_delegate(delegate) { - m_listener.notify = Listener::MainCallback; + m_internal.m_listener.notify = Listener::MainCallback; + m_internal.m_self_ptr = this; } void xtw::Listener::MainCallback(struct wl_listener *listener, void *data) { - static_cast(data)->Callback(); + container_of(listener, struct Listener::Internal, m_listener)->m_self_ptr->Callback(); } void @@ -553,7 +558,7 @@ xtw::Listener::Callback() void xtw::Listener::BindTo(struct wl_signal *s) { - wl_signal_add(s, &m_listener); + wl_signal_add(s, &m_internal.m_listener); } xtwc::Compositor::Compositor(struct weston_compositor *c) : From c4997b5f12c99361e9a2bbff0f3d85532511b793 Mon Sep 17 00:00:00 2001 From: Sam Spilsbury Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 44/59] wayland: Go through the view first, then to the surface This was an ABI break that happened earlier. Signed-off-by: memeka --- .../tests/wayland/XBMCWaylandTestExtension.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp b/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp index bfefb5587ed11..25310dd600b61 100644 --- a/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp +++ b/xbmc/windowing/tests/wayland/XBMCWaylandTestExtension.cpp @@ -679,15 +679,15 @@ xtwc::Compositor::Seat() struct weston_surface * xtwc::Compositor::TopSurface() { - struct weston_surface *surface; + struct weston_view *view; /* The strange semantics of wl_container_of means that we can't * return its result directly because it needs to have an * instantiation of the type */ - surface = wl_container_of(m_compositor->surface_list.prev, - surface, - link); - return surface; + view = wl_container_of(m_compositor->view_list.prev, + view, + link); + return view->surface; } void From b4ed4c08218ca69ca87dedf8b4a43dda5bb20fcd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 45/59] windowing/wayland: remove the DynamicDll code Signed-off-by: memeka --- xbmc/DllPaths_generated.h.in | 7 - xbmc/input/linux/XKBCommonKeymap.cpp | 74 ++---- xbmc/input/linux/XKBCommonKeymap.h | 15 +- xbmc/windowing/wayland/Callback.cpp | 15 +- xbmc/windowing/wayland/Callback.h | 6 +- xbmc/windowing/wayland/Compositor.cpp | 31 +-- xbmc/windowing/wayland/Compositor.h | 6 +- xbmc/windowing/wayland/Display.cpp | 22 +- xbmc/windowing/wayland/Display.h | 5 +- xbmc/windowing/wayland/DllWaylandClient.h | 193 -------------- xbmc/windowing/wayland/DllWaylandEgl.h | 65 ----- xbmc/windowing/wayland/DllXKBCommon.h | 92 ------- .../wayland/EGLNativeTypeWayland.cpp | 48 +--- xbmc/windowing/wayland/InputFactory.cpp | 15 +- xbmc/windowing/wayland/InputFactory.h | 10 +- xbmc/windowing/wayland/Keyboard.cpp | 40 +-- xbmc/windowing/wayland/Keyboard.h | 15 +- xbmc/windowing/wayland/OpenGLSurface.cpp | 21 +- xbmc/windowing/wayland/OpenGLSurface.h | 6 +- xbmc/windowing/wayland/Output.cpp | 15 +- xbmc/windowing/wayland/Output.h | 7 +- xbmc/windowing/wayland/Pointer.cpp | 22 +- xbmc/windowing/wayland/Pointer.h | 6 +- xbmc/windowing/wayland/PointerProcessor.cpp | 3 - xbmc/windowing/wayland/Region.cpp | 20 +- xbmc/windowing/wayland/Region.h | 6 +- xbmc/windowing/wayland/Registry.cpp | 38 +-- xbmc/windowing/wayland/Registry.h | 35 +-- xbmc/windowing/wayland/Seat.cpp | 36 +-- xbmc/windowing/wayland/Seat.h | 6 +- xbmc/windowing/wayland/Shell.cpp | 21 +- xbmc/windowing/wayland/Shell.h | 6 +- xbmc/windowing/wayland/ShellSurface.cpp | 29 +-- xbmc/windowing/wayland/ShellSurface.h | 6 +- xbmc/windowing/wayland/Surface.cpp | 31 +-- xbmc/windowing/wayland/Surface.h | 6 +- .../wayland/Wayland11EventQueueStrategy.cpp | 132 ---------- .../wayland/Wayland11EventQueueStrategy.h | 77 ------ .../wayland/Wayland12EventQueueStrategy.cpp | 22 +- .../wayland/Wayland12EventQueueStrategy.h | 6 +- xbmc/windowing/wayland/WaylandLibraries.cpp | 57 ---- xbmc/windowing/wayland/WaylandLibraries.h | 89 ------- xbmc/windowing/wayland/WaylandProtocol.h | 244 ------------------ xbmc/windowing/wayland/WinEventsWayland.cpp | 8 +- xbmc/windowing/wayland/WinEventsWayland.h | 7 +- xbmc/windowing/wayland/XBMCConnection.cpp | 93 +++---- xbmc/windowing/wayland/XBMCConnection.h | 11 +- xbmc/windowing/wayland/XBMCSurface.cpp | 42 +-- xbmc/windowing/wayland/XBMCSurface.h | 7 +- 49 files changed, 193 insertions(+), 1581 deletions(-) delete mode 100644 xbmc/windowing/wayland/DllWaylandClient.h delete mode 100644 xbmc/windowing/wayland/DllWaylandEgl.h delete mode 100644 xbmc/windowing/wayland/DllXKBCommon.h delete mode 100644 xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp delete mode 100644 xbmc/windowing/wayland/Wayland11EventQueueStrategy.h delete mode 100644 xbmc/windowing/wayland/WaylandLibraries.cpp delete mode 100644 xbmc/windowing/wayland/WaylandLibraries.h delete mode 100644 xbmc/windowing/wayland/WaylandProtocol.h diff --git a/xbmc/DllPaths_generated.h.in b/xbmc/DllPaths_generated.h.in index 76d6f3548fc47..a4d45307034eb 100644 --- a/xbmc/DllPaths_generated.h.in +++ b/xbmc/DllPaths_generated.h.in @@ -46,13 +46,6 @@ /* libbluray */ #define DLL_PATH_LIBBLURAY "@BLURAY_SONAME@" -/* wayland */ -#define DLL_PATH_WAYLAND_CLIENT "@WAYLAND_CLIENT_LIBRARY_SONAME@" -#define DLL_PATH_WAYLAND_EGL "@WAYLAND_EGL_LIBRARY_SONAME@" - -/* xkbcommon */ -#define DLL_PATH_XKBCOMMON "@XKBCOMMON_LIBRARY_SONAME@" - /* sse4 */ #define DLL_PATH_LIBSSE4 "special://xbmcbin/system/libsse4-@ARCH@.so" diff --git a/xbmc/input/linux/XKBCommonKeymap.cpp b/xbmc/input/linux/XKBCommonKeymap.cpp index d9f42f195163e..f9496022b84cd 100644 --- a/xbmc/input/linux/XKBCommonKeymap.cpp +++ b/xbmc/input/linux/XKBCommonKeymap.cpp @@ -29,17 +29,16 @@ #include "Application.h" -#include "windowing/wayland/DllXKBCommon.h" #include "XKBCommonKeymap.h" #include "Util.h" struct xkb_context * -CXKBKeymap::CreateXKBContext(IDllXKBCommon &xkbCommonLibrary) +CXKBKeymap::CreateXKBContext() { enum xkb_context_flags flags = static_cast(0); - struct xkb_context *context = xkbCommonLibrary.xkb_context_new(flags); + struct xkb_context *context = xkb_context_new(flags); /* It is the object who wants to create an XKBKeymap and not * XKBKeymap itself that owns the xkb_context. The @@ -73,7 +72,7 @@ CXKBKeymap::CreateXKBContext(IDllXKBCommon &xkbCommonLibrary) * from this function. */ struct xkb_keymap * -CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(IDllXKBCommon &xkbCommonLibrary, struct xkb_context *context, const int &fd, uint32_t size) +CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(struct xkb_context *context, const int &fd, uint32_t size) { const char *keymapString = static_cast(mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)); if (keymapString == MAP_FAILED) @@ -94,7 +93,7 @@ CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(IDllXKBCommon &xkbCommonLibrary, st enum xkb_keymap_compile_flags flags = static_cast(0); struct xkb_keymap *keymap = - xkbCommonLibrary.xkb_keymap_new_from_string(context, keymapString, XKB_KEYMAP_FORMAT_TEXT_V1, flags); + xkb_keymap_new_from_string(context, keymapString, XKB_KEYMAP_FORMAT_TEXT_V1, flags); /* Failure to compile a keymap is a runtime error and the caller * should handle it */ @@ -105,7 +104,7 @@ CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(IDllXKBCommon &xkbCommonLibrary, st } struct xkb_keymap * -CXKBKeymap::CreateXKBKeymapFromNames(IDllXKBCommon &xkbCommonLibrary, struct xkb_context *context, const std::string &rules, const std::string &model, const std::string &layout, const std::string &variant, const std::string &options) +CXKBKeymap::CreateXKBKeymapFromNames(struct xkb_context *context, const std::string &rules, const std::string &model, const std::string &layout, const std::string &variant, const std::string &options) { enum xkb_keymap_compile_flags flags = static_cast(0); @@ -120,7 +119,7 @@ CXKBKeymap::CreateXKBKeymapFromNames(IDllXKBCommon &xkbCommonLibrary, struct xkb }; struct xkb_keymap *keymap = - xkbCommonLibrary.xkb_keymap_new_from_names(context, &names, flags); + xkb_keymap_new_from_names(context, &names, flags); if (!keymap) throw std::runtime_error("Failed to compile keymap"); @@ -129,9 +128,9 @@ CXKBKeymap::CreateXKBKeymapFromNames(IDllXKBCommon &xkbCommonLibrary, struct xkb } struct xkb_state * -CXKBKeymap::CreateXKBStateFromKeymap(IDllXKBCommon &xkbCommonLibrary, struct xkb_keymap *keymap) +CXKBKeymap::CreateXKBStateFromKeymap(struct xkb_keymap *keymap) { - struct xkb_state *state = xkbCommonLibrary.xkb_state_new(keymap); + struct xkb_state *state = xkb_state_new(keymap); if (!state) throw std::runtime_error("Failed to create keyboard state"); @@ -151,45 +150,29 @@ CXKBKeymap::CreateXKBStateFromKeymap(IDllXKBCommon &xkbCommonLibrary, struct xkb * PRESSED MODIFIERS. Undefined behaviour will result if it is not * kept up to date. */ -CXKBKeymap::CXKBKeymap(IDllXKBCommon &xkbCommonLibrary, - struct xkb_keymap *keymap) : - m_xkbCommonLibrary(xkbCommonLibrary), +CXKBKeymap::CXKBKeymap(struct xkb_keymap *keymap) : m_keymap(keymap), - m_state(CreateXKBStateFromKeymap(xkbCommonLibrary, - keymap)), - m_internalLeftControlIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - XKB_MOD_NAME_CTRL)), - m_internalLeftShiftIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - XKB_MOD_NAME_SHIFT)), - m_internalLeftSuperIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - XKB_MOD_NAME_LOGO)), - m_internalLeftAltIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - XKB_MOD_NAME_ALT)), - m_internalLeftMetaIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - "Meta")), - m_internalRightControlIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - "RControl")), - m_internalRightShiftIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - "RShift")), - m_internalRightSuperIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - "Hyper")), - m_internalRightAltIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - "AltGr")), - m_internalRightMetaIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - "Meta")), - m_internalCapsLockIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - XKB_LED_NAME_CAPS)), - m_internalNumLockIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - XKB_LED_NAME_NUM)), - m_internalModeIndex(m_xkbCommonLibrary.xkb_keymap_mod_get_index(m_keymap, - XKB_LED_NAME_SCROLL)) + m_state(CreateXKBStateFromKeymap(keymap)), + m_internalLeftControlIndex(xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_CTRL)), + m_internalLeftShiftIndex(xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_SHIFT)), + m_internalLeftSuperIndex(xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_LOGO)), + m_internalLeftAltIndex(xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_ALT)), + m_internalLeftMetaIndex(xkb_keymap_mod_get_index(m_keymap, "Meta")), + m_internalRightControlIndex(xkb_keymap_mod_get_index(m_keymap, "RControl")), + m_internalRightShiftIndex(xkb_keymap_mod_get_index(m_keymap, "RShift")), + m_internalRightSuperIndex(xkb_keymap_mod_get_index(m_keymap, "Hyper")), + m_internalRightAltIndex(xkb_keymap_mod_get_index(m_keymap, "AltGr")), + m_internalRightMetaIndex(xkb_keymap_mod_get_index(m_keymap, "Meta")), + m_internalCapsLockIndex(xkb_keymap_mod_get_index(m_keymap, XKB_LED_NAME_CAPS)), + m_internalNumLockIndex(xkb_keymap_mod_get_index(m_keymap, XKB_LED_NAME_NUM)), + m_internalModeIndex(xkb_keymap_mod_get_index(m_keymap, XKB_LED_NAME_SCROLL)) { } CXKBKeymap::~CXKBKeymap() { - m_xkbCommonLibrary.xkb_state_unref(m_state); - m_xkbCommonLibrary.xkb_keymap_unref(m_keymap); + xkb_state_unref(m_state); + xkb_keymap_unref(m_keymap); } uint32_t @@ -204,7 +187,7 @@ CXKBKeymap::KeysymForKeycode(uint32_t code) const * a runtime_error which the client needs to handle. * * Codes sent generally have an offset of 8 */ - numSyms = m_xkbCommonLibrary.xkb_state_key_get_syms(m_state, code + 8, &syms); + numSyms = xkb_state_key_get_syms(m_state, code + 8, &syms); if (numSyms == 1) return static_cast(syms[0]); @@ -227,8 +210,7 @@ uint32_t CXKBKeymap::CurrentModifiers() const static_cast (XKB_STATE_DEPRESSED | XKB_STATE_LATCHED | XKB_STATE_LOCKED); - xkb_mod_mask_t mask = m_xkbCommonLibrary.xkb_state_serialize_mods(m_state, - components); + xkb_mod_mask_t mask = xkb_state_serialize_mods(m_state, components); return mask; } @@ -238,7 +220,7 @@ uint32_t CXKBKeymap::CurrentModifiers() const * THIS FUNCTION MUST BE CALLED WHENEVER MODIFIERS CHANGE */ void CXKBKeymap::UpdateMask(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { - m_xkbCommonLibrary.xkb_state_update_mask(m_state, depressed, latched, locked, 0, 0, group); + xkb_state_update_mask(m_state, depressed, latched, locked, 0, 0, group); } uint32_t CXKBKeymap::ActiveXBMCModifiers() const diff --git a/xbmc/input/linux/XKBCommonKeymap.h b/xbmc/input/linux/XKBCommonKeymap.h index d5fff4687da48..9fcf8f7af3bd4 100644 --- a/xbmc/input/linux/XKBCommonKeymap.h +++ b/xbmc/input/linux/XKBCommonKeymap.h @@ -28,21 +28,18 @@ struct xkb_state; typedef uint32_t xkb_mod_index_t; typedef uint32_t xkb_mask_index_t; -class IDllXKBCommon; - class CXKBKeymap : public ILinuxKeymap { public: - CXKBKeymap(IDllXKBCommon &m_xkbCommonLibrary, - struct xkb_keymap *keymap); + explicit CXKBKeymap(struct xkb_keymap *keymap); ~CXKBKeymap(); - static struct xkb_context * CreateXKBContext(IDllXKBCommon &xkbCommonLibrary); + static struct xkb_context * CreateXKBContext(); /* ReceiveXKBKeymapFromSharedMemory does not own the file descriptor, as such it takes a const reference to it */ - static struct xkb_keymap * ReceiveXKBKeymapFromSharedMemory(IDllXKBCommon &xkbCommonLibrary, struct xkb_context *, const int &fd, uint32_t size); - static struct xkb_state * CreateXKBStateFromKeymap(IDllXKBCommon &xkbCommonLibrary, struct xkb_keymap *keymap); - static struct xkb_keymap * CreateXKBKeymapFromNames(IDllXKBCommon &xkbCommonLibrary, struct xkb_context *context, const std::string &rules, const std::string &model, const std::string &layout, const std::string &variant, const std::string &options); + static struct xkb_keymap * ReceiveXKBKeymapFromSharedMemory(struct xkb_context *, const int &fd, uint32_t size); + static struct xkb_state * CreateXKBStateFromKeymap(struct xkb_keymap *keymap); + static struct xkb_keymap * CreateXKBKeymapFromNames(struct xkb_context *context, const std::string &rules, const std::string &model, const std::string &layout, const std::string &variant, const std::string &options); private: uint32_t KeysymForKeycode(uint32_t code) const; @@ -54,8 +51,6 @@ class CXKBKeymap : public ILinuxKeymap uint32_t XBMCKeysymForKeycode(uint32_t code) const; uint32_t ActiveXBMCModifiers() const; - IDllXKBCommon &m_xkbCommonLibrary; - struct xkb_keymap *m_keymap; struct xkb_state *m_state; diff --git a/xbmc/windowing/wayland/Callback.cpp b/xbmc/windowing/wayland/Callback.cpp index a332630aca9a6..2c729077bef58 100644 --- a/xbmc/windowing/wayland/Callback.cpp +++ b/xbmc/windowing/wayland/Callback.cpp @@ -19,8 +19,6 @@ */ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Callback.h" namespace xw = xbmc::wayland; @@ -30,23 +28,18 @@ const wl_callback_listener xw::Callback::m_listener = Callback::OnCallback }; -xw::Callback::Callback(IDllWaylandClient &clientLibrary, - struct wl_callback *callback, +xw::Callback::Callback(struct wl_callback *callback, const Func &func) : - m_clientLibrary(clientLibrary), m_callback(callback), m_func(func) { - protocol::AddListenerOnWaylandObject(m_clientLibrary, - m_callback, - &m_listener, - reinterpret_cast(this)); + wl_callback_add_listener(m_callback, &m_listener, + reinterpret_cast(this)); } xw::Callback::~Callback() { - protocol::DestroyWaylandObject(m_clientLibrary, - m_callback); + wl_callback_destroy(m_callback); } struct wl_callback * diff --git a/xbmc/windowing/wayland/Callback.h b/xbmc/windowing/wayland/Callback.h index 00fba8afd0ec2..a36a89c6d3eb0 100644 --- a/xbmc/windowing/wayland/Callback.h +++ b/xbmc/windowing/wayland/Callback.h @@ -23,8 +23,6 @@ #include -class IDllWaylandClient; - namespace xbmc { namespace wayland @@ -40,8 +38,7 @@ class Callback typedef std::function Func; - Callback(IDllWaylandClient &clientLibrary, - struct wl_callback *callback, + Callback(struct wl_callback *callback, const Func &func); ~Callback(); @@ -58,7 +55,6 @@ class Callback private: - IDllWaylandClient &m_clientLibrary; struct wl_callback *m_callback; Func m_func; }; diff --git a/xbmc/windowing/wayland/Compositor.cpp b/xbmc/windowing/wayland/Compositor.cpp index f7a1b1e9905b3..b71889194dff1 100644 --- a/xbmc/windowing/wayland/Compositor.cpp +++ b/xbmc/windowing/wayland/Compositor.cpp @@ -19,23 +19,18 @@ */ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Compositor.h" namespace xw = xbmc::wayland; -xw::Compositor::Compositor(IDllWaylandClient &clientLibrary, - struct wl_compositor *compositor) : - m_clientLibrary(clientLibrary), +xw::Compositor::Compositor(struct wl_compositor *compositor) : m_compositor(compositor) { } xw::Compositor::~Compositor() { - protocol::DestroyWaylandObject(m_clientLibrary, - m_compositor); + wl_compositor_destroy(m_compositor); } struct wl_compositor * @@ -47,29 +42,11 @@ xw::Compositor::GetWlCompositor() struct wl_surface * xw::Compositor::CreateSurface() const { - struct wl_surface *surface = - protocol::CreateWaylandObject(m_clientLibrary, - m_compositor, - m_clientLibrary.Get_wl_surface_interface()); - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_compositor, - WL_COMPOSITOR_CREATE_SURFACE, - surface); - return surface; + return wl_compositor_create_surface(m_compositor); } struct wl_region * xw::Compositor::CreateRegion() const { - struct wl_region *region = - protocol::CreateWaylandObject(m_clientLibrary, - m_compositor, - m_clientLibrary.Get_wl_region_interface ()); - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_compositor, - WL_COMPOSITOR_CREATE_REGION, - region); - return region; + return wl_compositor_create_region(m_compositor); } diff --git a/xbmc/windowing/wayland/Compositor.h b/xbmc/windowing/wayland/Compositor.h index 20be4141845b0..0848743423b74 100644 --- a/xbmc/windowing/wayland/Compositor.h +++ b/xbmc/windowing/wayland/Compositor.h @@ -23,8 +23,6 @@ struct wl_compositor; struct wl_surface; struct wl_region; -class IDllWaylandClient; - namespace xbmc { namespace wayland @@ -33,8 +31,7 @@ class Compositor { public: - Compositor(IDllWaylandClient &clientLibrary, - struct wl_compositor *compositor); + explicit Compositor(struct wl_compositor *compositor); ~Compositor(); Compositor(const Compositor &) = delete; @@ -54,7 +51,6 @@ class Compositor private: - IDllWaylandClient &m_clientLibrary; struct wl_compositor *m_compositor; }; } diff --git a/xbmc/windowing/wayland/Display.cpp b/xbmc/windowing/wayland/Display.cpp index 6e59db550219c..e4a9456743797 100644 --- a/xbmc/windowing/wayland/Display.cpp +++ b/xbmc/windowing/wayland/Display.cpp @@ -25,8 +25,6 @@ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Display.h" namespace xw = xbmc::wayland; @@ -55,9 +53,8 @@ xw::WaylandDisplayListener::GetInstance() std::unique_ptr xw::WaylandDisplayListener::m_instance; -xw::Display::Display(IDllWaylandClient &clientLibrary) : - m_clientLibrary(clientLibrary), - m_display(m_clientLibrary.wl_display_connect(NULL)) +xw::Display::Display() : + m_display(wl_display_connect(NULL)) { /* wl_display_connect won't throw when it fails, but it does * return NULL on failure. If this object would be incomplete @@ -76,8 +73,8 @@ xw::Display::Display(IDllWaylandClient &clientLibrary) : xw::Display::~Display() { - m_clientLibrary.wl_display_flush(m_display); - m_clientLibrary.wl_display_disconnect(m_display); + wl_display_flush(m_display); + wl_display_disconnect(m_display); } struct wl_display * @@ -101,14 +98,5 @@ xw::Display::GetEGLNativeDisplay() struct wl_callback * xw::Display::Sync() { - struct wl_callback *callback = - protocol::CreateWaylandObject (m_clientLibrary, - m_display, - m_clientLibrary.Get_wl_callback_interface()); - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_display, - WL_DISPLAY_SYNC, - callback); - return callback; + return wl_display_sync(m_display); } diff --git a/xbmc/windowing/wayland/Display.h b/xbmc/windowing/wayland/Display.h index 987e8116a00ba..bc403a654a42b 100644 --- a/xbmc/windowing/wayland/Display.h +++ b/xbmc/windowing/wayland/Display.h @@ -22,8 +22,6 @@ #include #include -class IDllWaylandClient; - struct wl_display; struct wl_callback; @@ -37,7 +35,7 @@ class Display { public: - Display(IDllWaylandClient &clientLibrary); + Display(); ~Display(); Display(const Display &) = delete; @@ -49,7 +47,6 @@ class Display private: - IDllWaylandClient &m_clientLibrary; struct wl_display *m_display; }; diff --git a/xbmc/windowing/wayland/DllWaylandClient.h b/xbmc/windowing/wayland/DllWaylandClient.h deleted file mode 100644 index edb6189edb2a4..0000000000000 --- a/xbmc/windowing/wayland/DllWaylandClient.h +++ /dev/null @@ -1,193 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2005-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) - #include "config.h" -#endif - -#include - -#include "utils/log.h" -#include "DynamicDll.h" - -struct wl_proxy; -struct wl_interface; - -struct wl_display; -struct wl_registry; -struct wl_callback; -struct wl_compositor; -struct wl_shell; -struct wl_shell_surface; -struct wl_surface; -struct wl_seat; -struct wl_pointer; -struct wl_keyboard; -struct wl_output; -struct wl_region; - -extern const struct wl_interface wl_display_interface; -extern const struct wl_interface wl_registry_interface; -extern const struct wl_interface wl_callback_interface; -extern const struct wl_interface wl_compositor_interface; -extern const struct wl_interface wl_shell_interface; -extern const struct wl_interface wl_shell_surface_interface; -extern const struct wl_interface wl_surface_interface; -extern const struct wl_interface wl_seat_interface; -extern const struct wl_interface wl_pointer_interface; -extern const struct wl_interface wl_keyboard_interface; -extern const struct wl_interface wl_output_interface; -extern const struct wl_interface wl_region_interface; - -class IDllWaylandClient -{ -public: - typedef void(*wl_proxy_marshal_func)(struct wl_proxy *, - uint32_t, - ...); - typedef void(*wl_proxy_listener_func)(void); - typedef int(*wl_display_read_events_func)(struct wl_display *); - typedef int(*wl_display_prepare_read_func)(struct wl_display *); - - virtual struct wl_interface ** Get_wl_display_interface() = 0; - virtual struct wl_interface ** Get_wl_registry_interface() = 0; - virtual struct wl_interface ** Get_wl_callback_interface() = 0; - virtual struct wl_interface ** Get_wl_compositor_interface() = 0; - virtual struct wl_interface ** Get_wl_shell_interface() = 0; - virtual struct wl_interface ** Get_wl_shell_surface_interface() = 0; - virtual struct wl_interface ** Get_wl_surface_interface() = 0; - virtual struct wl_interface ** Get_wl_seat_interface() = 0; - virtual struct wl_interface ** Get_wl_pointer_interface() = 0; - virtual struct wl_interface ** Get_wl_keyboard_interface() = 0; - virtual struct wl_interface ** Get_wl_output_interface() = 0; - virtual struct wl_interface ** Get_wl_region_interface() = 0; - - virtual struct wl_display * wl_display_connect(const char *) = 0; - virtual void wl_display_disconnect(struct wl_display *) = 0; - virtual int wl_display_get_fd(struct wl_display *) = 0; - virtual wl_display_prepare_read_func wl_display_prepare_read_proc() = 0; - virtual wl_display_read_events_func wl_display_read_events_proc() = 0; - virtual int wl_display_dispatch_pending(struct wl_display *) = 0; - virtual int wl_display_dispatch(struct wl_display *) = 0; - virtual int wl_display_flush(struct wl_display *) = 0; - - virtual wl_proxy_marshal_func wl_proxy_marshaller() = 0; - - virtual struct wl_proxy * wl_proxy_create(struct wl_proxy *, - const struct wl_interface *) = 0; - virtual void wl_proxy_destroy(struct wl_proxy *) = 0; - virtual int wl_proxy_add_listener(struct wl_proxy *, - wl_proxy_listener_func *, - void *) = 0; - - virtual ~IDllWaylandClient() {} -}; - -class DllWaylandClient : public DllDynamic, public IDllWaylandClient -{ - DECLARE_DLL_WRAPPER(DllWaylandClient, DLL_PATH_WAYLAND_CLIENT) - - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_display_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_registry_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_callback_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_compositor_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_shell_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_shell_surface_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_surface_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_seat_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_pointer_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_keyboard_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_output_interface); - DEFINE_GLOBAL_PTR(struct wl_interface *, wl_region_interface); - - DEFINE_METHOD1(struct wl_display *, wl_display_connect, (const char *p1)); - DEFINE_METHOD1(void, wl_display_disconnect, (struct wl_display *p1)); - DEFINE_METHOD1(int, wl_display_get_fd, (struct wl_display *p1)); - DEFINE_METHOD_FP(int, wl_display_prepare_read, (struct wl_display *p1)); - DEFINE_METHOD_FP(int, wl_display_read_events, (struct wl_display *p1)); - DEFINE_METHOD1(int, wl_display_dispatch_pending, (struct wl_display *p1)); - DEFINE_METHOD1(int, wl_display_dispatch, (struct wl_display *p1)); - DEFINE_METHOD1(int, wl_display_flush, (struct wl_display *p1)); - - /* We need to resolve wl_proxy_marshal as a function pointer as it - * takes varargs */ - DEFINE_METHOD_FP(void, - wl_proxy_marshal, - (struct wl_proxy *p1, uint32_t p2, ...)); - - DEFINE_METHOD2(struct wl_proxy *, - wl_proxy_create, - (struct wl_proxy *p1, const struct wl_interface *p2)); - DEFINE_METHOD1(void, wl_proxy_destroy, (struct wl_proxy *p1)); - DEFINE_METHOD3(int, - wl_proxy_add_listener, - (struct wl_proxy *p1, - wl_proxy_listener_func *p2, - void *p3)); - - BEGIN_METHOD_RESOLVE() - RESOLVE_METHOD(wl_display_interface) - RESOLVE_METHOD(wl_registry_interface) - RESOLVE_METHOD(wl_callback_interface) - RESOLVE_METHOD(wl_compositor_interface) - RESOLVE_METHOD(wl_shell_interface) - RESOLVE_METHOD(wl_shell_surface_interface) - RESOLVE_METHOD(wl_surface_interface) - RESOLVE_METHOD(wl_seat_interface) - RESOLVE_METHOD(wl_pointer_interface) - RESOLVE_METHOD(wl_keyboard_interface) - RESOLVE_METHOD(wl_output_interface) - RESOLVE_METHOD(wl_region_interface) - - RESOLVE_METHOD(wl_display_connect) - RESOLVE_METHOD(wl_display_disconnect) - RESOLVE_METHOD(wl_display_get_fd) - RESOLVE_METHOD_OPTIONAL_FP(wl_display_prepare_read) - RESOLVE_METHOD_OPTIONAL_FP(wl_display_read_events) - RESOLVE_METHOD(wl_display_dispatch_pending) - RESOLVE_METHOD(wl_display_dispatch) - RESOLVE_METHOD(wl_display_flush) - RESOLVE_METHOD_FP(wl_proxy_marshal) - RESOLVE_METHOD(wl_proxy_create) - RESOLVE_METHOD(wl_proxy_destroy) - RESOLVE_METHOD(wl_proxy_add_listener) - END_METHOD_RESOLVE() - -public: - - /* This overload returns the function pointer to wl_proxy_marshal - * so that clients can call it directly */ - wl_proxy_marshal_func wl_proxy_marshaller() - { - return DllWaylandClient::wl_proxy_marshal; - } - - wl_display_prepare_read_func wl_display_prepare_read_proc() - { - return DllWaylandClient::wl_display_prepare_read; - } - - wl_display_read_events_func wl_display_read_events_proc() - { - return DllWaylandClient::wl_display_read_events; - } -}; diff --git a/xbmc/windowing/wayland/DllWaylandEgl.h b/xbmc/windowing/wayland/DllWaylandEgl.h deleted file mode 100644 index c72d3f9d804cb..0000000000000 --- a/xbmc/windowing/wayland/DllWaylandEgl.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2005-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) - #include "config.h" -#endif -#include "utils/log.h" -#include "DynamicDll.h" - -struct wl_surface; -struct wl_egl_window; - -class IDllWaylandEGL -{ -public: - virtual ~IDllWaylandEGL() {} - virtual struct wl_egl_window * wl_egl_window_create(struct wl_surface *, - int width, - int height) = 0; - virtual void wl_egl_window_destroy(struct wl_egl_window *) = 0; - virtual void wl_egl_window_resize(struct wl_egl_window *, - int width, int height, - int dx, int dy) = 0; -}; - -class DllWaylandEGL : public DllDynamic, public IDllWaylandEGL -{ - DECLARE_DLL_WRAPPER(DllWaylandEGL, DLL_PATH_WAYLAND_EGL) - - DEFINE_METHOD3(struct wl_egl_window *, - wl_egl_window_create, - (struct wl_surface *p1, int p2, int p3)); - DEFINE_METHOD1(void, wl_egl_window_destroy, (struct wl_egl_window *p1)); - DEFINE_METHOD5(void, - wl_egl_window_resize, - (struct wl_egl_window *p1, - int p2, - int p3, - int p4, - int p5)); - BEGIN_METHOD_RESOLVE() - RESOLVE_METHOD(wl_egl_window_create) - RESOLVE_METHOD(wl_egl_window_destroy) - RESOLVE_METHOD(wl_egl_window_resize) - END_METHOD_RESOLVE() -}; diff --git a/xbmc/windowing/wayland/DllXKBCommon.h b/xbmc/windowing/wayland/DllXKBCommon.h deleted file mode 100644 index 97a721b89ea1c..0000000000000 --- a/xbmc/windowing/wayland/DllXKBCommon.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2005-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) - #include "config.h" -#endif -#include -#include "utils/log.h" -#include "DynamicDll.h" - -class IDllXKBCommon -{ -public: - virtual ~IDllXKBCommon() {} - - virtual struct xkb_context * xkb_context_new(enum xkb_context_flags) = 0; - virtual void xkb_context_unref(struct xkb_context *) = 0; - virtual struct xkb_keymap * xkb_keymap_new_from_string(struct xkb_context *, - const char *, - enum xkb_keymap_format, - enum xkb_keymap_compile_flags) = 0; - virtual struct xkb_keymap * xkb_keymap_new_from_names(struct xkb_context *, - const struct xkb_rule_names *, - enum xkb_keymap_compile_flags) = 0; - virtual xkb_mod_index_t xkb_keymap_mod_get_index(struct xkb_keymap *, - const char *) = 0; - virtual void xkb_keymap_unref(struct xkb_keymap *) = 0; - virtual struct xkb_state * xkb_state_new(struct xkb_keymap *) = 0; - virtual xkb_mod_mask_t xkb_state_serialize_mods(struct xkb_state *, - enum xkb_state_component) = 0; - virtual enum xkb_state_component xkb_state_update_mask (struct xkb_state *, - xkb_mod_mask_t, - xkb_mod_mask_t, - xkb_mod_mask_t, - xkb_layout_index_t, - xkb_layout_index_t, - xkb_layout_index_t) = 0; - virtual uint32_t xkb_state_key_get_syms(struct xkb_state *, - uint32_t, - const xkb_keysym_t **) = 0; - virtual void xkb_state_unref(struct xkb_state *) = 0; -}; - -class DllXKBCommon : public DllDynamic, public IDllXKBCommon -{ - DECLARE_DLL_WRAPPER(DllXKBCommon, DLL_PATH_XKBCOMMON) - - DEFINE_METHOD1(struct xkb_context *, xkb_context_new, (enum xkb_context_flags p1)); - DEFINE_METHOD1(void, xkb_context_unref, (struct xkb_context *p1)); - DEFINE_METHOD4(struct xkb_keymap *, xkb_keymap_new_from_string, (struct xkb_context *p1, const char *p2, enum xkb_keymap_format p3, enum xkb_keymap_compile_flags p4)); - DEFINE_METHOD3(struct xkb_keymap *, xkb_keymap_new_from_names, (struct xkb_context *p1, const struct xkb_rule_names *p2, enum xkb_keymap_compile_flags p3)); - DEFINE_METHOD2(xkb_mod_index_t, xkb_keymap_mod_get_index, (struct xkb_keymap *p1, const char *p2)); - DEFINE_METHOD1(void, xkb_keymap_unref, (struct xkb_keymap *p1)); - DEFINE_METHOD1(struct xkb_state *, xkb_state_new, (struct xkb_keymap *p1)); - DEFINE_METHOD2(xkb_mod_mask_t, xkb_state_serialize_mods, (struct xkb_state *p1, enum xkb_state_component p2)); - DEFINE_METHOD7(enum xkb_state_component, xkb_state_update_mask, (struct xkb_state *p1, xkb_mod_mask_t p2, xkb_mod_mask_t p3, xkb_mod_mask_t p4, xkb_layout_index_t p5, xkb_layout_index_t p6, xkb_layout_index_t p7)); - DEFINE_METHOD3(uint32_t, xkb_state_key_get_syms, (struct xkb_state *p1, uint32_t p2, const xkb_keysym_t **p3)); - DEFINE_METHOD1(void, xkb_state_unref, (struct xkb_state *p1)); - - BEGIN_METHOD_RESOLVE() - RESOLVE_METHOD(xkb_context_new) - RESOLVE_METHOD(xkb_context_unref) - RESOLVE_METHOD(xkb_keymap_new_from_string) - RESOLVE_METHOD(xkb_keymap_new_from_names) - RESOLVE_METHOD(xkb_keymap_mod_get_index) - RESOLVE_METHOD(xkb_keymap_unref) - RESOLVE_METHOD(xkb_state_new) - RESOLVE_METHOD(xkb_state_serialize_mods) - RESOLVE_METHOD(xkb_state_update_mask) - RESOLVE_METHOD(xkb_state_key_get_syms) - RESOLVE_METHOD(xkb_state_unref) - END_METHOD_RESOLVE() -}; diff --git a/xbmc/windowing/wayland/EGLNativeTypeWayland.cpp b/xbmc/windowing/wayland/EGLNativeTypeWayland.cpp index ab9000cbc82b5..3a077aa67f1bf 100644 --- a/xbmc/windowing/wayland/EGLNativeTypeWayland.cpp +++ b/xbmc/windowing/wayland/EGLNativeTypeWayland.cpp @@ -32,17 +32,11 @@ #include #include -#include "DllWaylandClient.h" -#include "DllWaylandEgl.h" -#include "DllXKBCommon.h" -#include "WaylandProtocol.h" - #include "guilib/gui3d.h" #include "utils/log.h" #include "windowing/WinEvents.h" #include "WinEventsWayland.h" -#include "WaylandLibraries.h" #include "XBMCConnection.h" #include "XBMCSurface.h" @@ -57,35 +51,10 @@ class CEGLNativeTypeWayland::Private { public: - std::unique_ptr m_libraries; std::unique_ptr m_connection; std::unique_ptr m_surface; - - bool LoadWaylandLibraries(); - void UnloadWaylandLibraries(); }; -bool CEGLNativeTypeWayland::Private::LoadWaylandLibraries() -{ - try - { - m_libraries.reset(new xw::Libraries()); - } - catch (const std::runtime_error &err) - { - CLog::Log(LOGWARNING, "%s: %s\n", - __FUNCTION__, err.what()); - return false; - } - - return true; -} - -void CEGLNativeTypeWayland::Private::UnloadWaylandLibraries() -{ - m_libraries.reset(); -} - #else class CEGLNativeTypeWayland::Private { @@ -104,12 +73,6 @@ CEGLNativeTypeWayland::~CEGLNativeTypeWayland() bool CEGLNativeTypeWayland::CheckCompatibility() { #if defined(HAVE_WAYLAND) - /* FIXME: - * There appears to be a bug in DllDynamic::CanLoad() which causes - * it to always return false. We are just loading the library - * directly at CheckCompatibility time now */ - if (!priv->LoadWaylandLibraries()) - return false; return true; #else @@ -123,9 +86,6 @@ void CEGLNativeTypeWayland::Initialize() void CEGLNativeTypeWayland::Destroy() { -#if defined(HAVE_WAYLAND) - priv->UnloadWaylandLibraries(); -#endif } int CEGLNativeTypeWayland::GetQuirks() @@ -172,9 +132,7 @@ bool CEGLNativeTypeWayland::CreateNativeDisplay() CWinEvents::MessagePump }; - priv->m_connection.reset(new xw::XBMCConnection(priv->m_libraries->ClientLibrary(), - priv->m_libraries->XKBCommonLibrary(), - injector)); + priv->m_connection.reset(new xw::XBMCConnection(injector)); } catch (const std::runtime_error &err) { @@ -222,9 +180,7 @@ bool CEGLNativeTypeWayland::CreateNativeWindow() CWinEventsWayland::SetXBMCSurface }; - priv->m_surface.reset(new xw::XBMCSurface(priv->m_libraries->ClientLibrary(), - priv->m_libraries->EGLLibrary(), - injector, + priv->m_surface.reset(new xw::XBMCSurface(injector, priv->m_connection->GetCompositor(), priv->m_connection->GetShell(), info.iScreenWidth, diff --git a/xbmc/windowing/wayland/InputFactory.cpp b/xbmc/windowing/wayland/InputFactory.cpp index c0f4a47f60236..063f36f9317c0 100644 --- a/xbmc/windowing/wayland/InputFactory.cpp +++ b/xbmc/windowing/wayland/InputFactory.cpp @@ -26,16 +26,12 @@ namespace xw = xbmc::wayland; -xbmc::InputFactory::InputFactory(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - struct wl_seat *seat, +xbmc::InputFactory::InputFactory(struct wl_seat *seat, IEventListener &dispatch, ITimeoutManager &timeouts) : - m_clientLibrary(clientLibrary), - m_xkbCommonLibrary(xkbCommonLibrary), m_pointerProcessor(dispatch, *this), m_keyboardProcessor(dispatch, timeouts), - m_seat(new xw::Seat(clientLibrary, seat, *this)) + m_seat(new xw::Seat(seat, *this)) { } @@ -57,8 +53,7 @@ bool xbmc::InputFactory::InsertPointer(struct wl_pointer *p) if (m_pointer.get()) return false; - m_pointer.reset(new xw::Pointer(m_clientLibrary, - p, + m_pointer.reset(new xw::Pointer(p, m_pointerProcessor)); return true; } @@ -68,9 +63,7 @@ bool xbmc::InputFactory::InsertKeyboard(struct wl_keyboard *k) if (m_keyboard.get()) return false; - m_keyboard.reset(new xw::Keyboard(m_clientLibrary, - m_xkbCommonLibrary, - k, + m_keyboard.reset(new xw::Keyboard(k, m_keyboardProcessor)); return true; } diff --git a/xbmc/windowing/wayland/InputFactory.h b/xbmc/windowing/wayland/InputFactory.h index e46c39c991930..cb2980b16606d 100644 --- a/xbmc/windowing/wayland/InputFactory.h +++ b/xbmc/windowing/wayland/InputFactory.h @@ -29,9 +29,6 @@ #include -class IDllWaylandClient; -class IDllXKBCommon; - struct wl_keyboard; struct wl_pointer; struct wl_seat; @@ -49,9 +46,7 @@ class InputFactory : { public: - InputFactory(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - struct wl_seat *seat, + InputFactory(struct wl_seat *seat, IEventListener &dispatch, ITimeoutManager &timeouts); @@ -70,9 +65,6 @@ class InputFactory : void RemovePointer(); void RemoveKeyboard(); - IDllWaylandClient &m_clientLibrary; - IDllXKBCommon &m_xkbCommonLibrary; - PointerProcessor m_pointerProcessor; KeyboardProcessor m_keyboardProcessor; diff --git a/xbmc/windowing/wayland/Keyboard.cpp b/xbmc/windowing/wayland/Keyboard.cpp index 1580640d907f3..d86e412d955e4 100644 --- a/xbmc/windowing/wayland/Keyboard.cpp +++ b/xbmc/windowing/wayland/Keyboard.cpp @@ -24,10 +24,8 @@ #include "utils/ScopeExit.hxx" #include +#include -#include "DllWaylandClient.h" -#include "DllXKBCommon.h" -#include "WaylandProtocol.h" #include "input/linux/XKBCommonKeymap.h" #include "Keyboard.h" @@ -44,40 +42,31 @@ const struct wl_keyboard_listener xw::Keyboard::m_listener = namespace { -void DestroyXKBCommonContext(struct xkb_context *context, - IDllXKBCommon &xkbCommonLibrary) +void DestroyXKBCommonContext(struct xkb_context *context) { - xkbCommonLibrary.xkb_context_unref(context); + xkb_context_unref(context); } } void xw::Keyboard::XkbContextDeleter::operator()(struct xkb_context *c) { - DestroyXKBCommonContext(c, m_xkbCommonLibrary); + DestroyXKBCommonContext(c); } -xw::Keyboard::Keyboard(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - struct wl_keyboard *keyboard, +xw::Keyboard::Keyboard(struct wl_keyboard *keyboard, IKeyboardReceiver &receiver) : - m_clientLibrary(clientLibrary), - m_xkbCommonLibrary(xkbCommonLibrary), - m_xkbCommonContext(CXKBKeymap::CreateXKBContext(m_xkbCommonLibrary), - XkbContextDeleter(xkbCommonLibrary)), + m_xkbCommonContext(CXKBKeymap::CreateXKBContext(), + XkbContextDeleter()), m_keyboard(keyboard), m_reciever(receiver) { - protocol::AddListenerOnWaylandObject(m_clientLibrary, - m_keyboard, - &m_listener, - this); + wl_keyboard_add_listener(m_keyboard, &m_listener, this); } xw::Keyboard::~Keyboard() { - protocol::DestroyWaylandObject(m_clientLibrary, - m_keyboard); + wl_keyboard_destroy(m_keyboard); } void xw::Keyboard::HandleKeymapCallback(void *data, @@ -166,20 +155,17 @@ void xw::Keyboard::HandleKeymap(uint32_t format, /* Either throws or returns a valid xkb_keymap * */ struct xkb_keymap *keymap = - CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(m_xkbCommonLibrary, - m_xkbCommonContext.get(), + CXKBKeymap::ReceiveXKBKeymapFromSharedMemory(m_xkbCommonContext.get(), fd, size); - auto &xkbCommonLibrary = m_xkbCommonLibrary; - AtScopeExit(&xkbCommonLibrary, &successfullyCreatedKeyboard, keymap) + AtScopeExit(&successfullyCreatedKeyboard, keymap) { if (!successfullyCreatedKeyboard) - xkbCommonLibrary.xkb_keymap_unref(keymap); + xkb_keymap_unref(keymap); }; - m_keymap.reset(new CXKBKeymap(m_xkbCommonLibrary, - keymap)); + m_keymap.reset(new CXKBKeymap(keymap)); successfullyCreatedKeyboard = true; diff --git a/xbmc/windowing/wayland/Keyboard.h b/xbmc/windowing/wayland/Keyboard.h index bcc65fcb3e2a9..7858ccbb746ac 100644 --- a/xbmc/windowing/wayland/Keyboard.h +++ b/xbmc/windowing/wayland/Keyboard.h @@ -25,9 +25,6 @@ #include "input/linux/Keymap.h" -class IDllWaylandClient; -class IDllXKBCommon; - struct xkb_context; namespace xbmc @@ -76,9 +73,7 @@ class Keyboard { public: - Keyboard(IDllWaylandClient &, - IDllXKBCommon &, - struct wl_keyboard *, + Keyboard(struct wl_keyboard *, IKeyboardReceiver &); ~Keyboard(); @@ -137,15 +132,7 @@ class Keyboard static const struct wl_keyboard_listener m_listener; - IDllWaylandClient &m_clientLibrary; - IDllXKBCommon &m_xkbCommonLibrary; - struct XkbContextDeleter { - IDllXKBCommon &m_xkbCommonLibrary; - - constexpr explicit XkbContextDeleter(IDllXKBCommon &xkbCommonLibrary) - :m_xkbCommonLibrary(xkbCommonLibrary) {} - void operator()(struct xkb_context *c); }; diff --git a/xbmc/windowing/wayland/OpenGLSurface.cpp b/xbmc/windowing/wayland/OpenGLSurface.cpp index 2aac14a049e63..28a336e399928 100644 --- a/xbmc/windowing/wayland/OpenGLSurface.cpp +++ b/xbmc/windowing/wayland/OpenGLSurface.cpp @@ -20,25 +20,20 @@ #include #include -#include "DllWaylandEgl.h" #include "OpenGLSurface.h" namespace xw = xbmc::wayland; -xw::OpenGLSurface::OpenGLSurface(IDllWaylandEGL &eglLibrary, - struct wl_surface *surface, +xw::OpenGLSurface::OpenGLSurface(struct wl_surface *surface, int width, int height) : - m_eglLibrary(eglLibrary), - m_eglWindow(m_eglLibrary.wl_egl_window_create(surface, - width, - height)) + m_eglWindow(wl_egl_window_create(surface, width, height)) { } xw::OpenGLSurface::~OpenGLSurface() { - m_eglLibrary.wl_egl_window_destroy(m_eglWindow); + wl_egl_window_destroy(m_eglWindow); } struct wl_egl_window * @@ -56,9 +51,9 @@ xw::OpenGLSurface::GetEGLNativeWindow() void xw::OpenGLSurface::Resize(int width, int height) { - m_eglLibrary.wl_egl_window_resize(m_eglWindow, - width, - height, - 0, - 0); + wl_egl_window_resize(m_eglWindow, + width, + height, + 0, + 0); } diff --git a/xbmc/windowing/wayland/OpenGLSurface.h b/xbmc/windowing/wayland/OpenGLSurface.h index 58c880ab63384..c2b425f6e1df5 100644 --- a/xbmc/windowing/wayland/OpenGLSurface.h +++ b/xbmc/windowing/wayland/OpenGLSurface.h @@ -20,8 +20,6 @@ * */ -class IDllWaylandEGL; - struct wl_surface; struct wl_egl_window; @@ -35,8 +33,7 @@ class OpenGLSurface { public: - OpenGLSurface(IDllWaylandEGL &eglLibrary, - struct wl_surface *surface, + OpenGLSurface(struct wl_surface *surface, int32_t width, int32_t height); ~OpenGLSurface(); @@ -50,7 +47,6 @@ class OpenGLSurface private: - IDllWaylandEGL &m_eglLibrary; struct wl_egl_window *m_eglWindow; }; } diff --git a/xbmc/windowing/wayland/Output.cpp b/xbmc/windowing/wayland/Output.cpp index 14cb8c75a906c..5ad2f91ad42f0 100644 --- a/xbmc/windowing/wayland/Output.cpp +++ b/xbmc/windowing/wayland/Output.cpp @@ -23,8 +23,6 @@ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Output.h" namespace xw = xbmc::wayland; @@ -37,24 +35,19 @@ const wl_output_listener xw::Output::m_listener = Output::ModeCallback }; -xw::Output::Output(IDllWaylandClient &clientLibrary, - struct wl_output *output) : - m_clientLibrary(clientLibrary), +xw::Output::Output(struct wl_output *output) : m_output(output), m_scaleFactor(1.0), m_currentValid(false), m_preferredValid(false) { - protocol::AddListenerOnWaylandObject(m_clientLibrary, - m_output, - &m_listener, - reinterpret_cast(this)); + wl_output_add_listener(m_output, &m_listener, + reinterpret_cast(this)); } xw::Output::~Output() { - protocol::DestroyWaylandObject(m_clientLibrary, - m_output); + wl_output_destroy(m_output); } struct wl_output * diff --git a/xbmc/windowing/wayland/Output.h b/xbmc/windowing/wayland/Output.h index b143c98db1193..8653d6f3ed303 100644 --- a/xbmc/windowing/wayland/Output.h +++ b/xbmc/windowing/wayland/Output.h @@ -23,8 +23,6 @@ #include -class IDllWaylandClient; - namespace xbmc { namespace wayland @@ -33,8 +31,7 @@ struct Output { public: - Output(IDllWaylandClient &, - struct wl_output *); + Output(struct wl_output *); ~Output(); Output(const Output &) = delete; @@ -132,8 +129,6 @@ struct Output void Scale(int32_t); void Done(); - IDllWaylandClient &m_clientLibrary; - struct wl_output *m_output; PhysicalGeometry m_geometry; diff --git a/xbmc/windowing/wayland/Pointer.cpp b/xbmc/windowing/wayland/Pointer.cpp index 1422be698f47e..9a4082c431f1d 100644 --- a/xbmc/windowing/wayland/Pointer.cpp +++ b/xbmc/windowing/wayland/Pointer.cpp @@ -23,8 +23,6 @@ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Pointer.h" namespace xw = xbmc::wayland; @@ -38,23 +36,17 @@ const struct wl_pointer_listener xw::Pointer::m_listener = Pointer::HandleAxisCallback }; -xw::Pointer::Pointer(IDllWaylandClient &clientLibrary, - struct wl_pointer *pointer, +xw::Pointer::Pointer(struct wl_pointer *pointer, IPointerReceiver &receiver) : - m_clientLibrary(clientLibrary), m_pointer(pointer), m_receiver(receiver) { - protocol::AddListenerOnWaylandObject(m_clientLibrary, - pointer, - &m_listener, - this); + wl_pointer_add_listener(pointer, &m_listener, this); } xw::Pointer::~Pointer() { - protocol::DestroyWaylandObject(m_clientLibrary, - m_pointer); + wl_pointer_destroy(m_pointer); } void xw::Pointer::SetCursor(uint32_t serial, @@ -62,13 +54,7 @@ void xw::Pointer::SetCursor(uint32_t serial, int32_t hotspot_x, int32_t hotspot_y) { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_pointer, - WL_POINTER_SET_CURSOR, - serial, - surface, - hotspot_x, - hotspot_y); + wl_pointer_set_cursor(m_pointer, serial, surface, hotspot_x, hotspot_y); } void xw::Pointer::HandleEnterCallback(void *data, diff --git a/xbmc/windowing/wayland/Pointer.h b/xbmc/windowing/wayland/Pointer.h index 161580f511435..0309f9b5bd62e 100644 --- a/xbmc/windowing/wayland/Pointer.h +++ b/xbmc/windowing/wayland/Pointer.h @@ -21,8 +21,6 @@ */ #include -class IDllWaylandClient; - namespace xbmc { namespace wayland @@ -57,8 +55,7 @@ class Pointer { public: - Pointer(IDllWaylandClient &, - struct wl_pointer *, + Pointer(struct wl_pointer *, IPointerReceiver &); ~Pointer(); @@ -120,7 +117,6 @@ class Pointer static const struct wl_pointer_listener m_listener; - IDllWaylandClient &m_clientLibrary; struct wl_pointer *m_pointer; IPointerReceiver &m_receiver; }; diff --git a/xbmc/windowing/wayland/PointerProcessor.cpp b/xbmc/windowing/wayland/PointerProcessor.cpp index b64e9b247e96f..8eb2ceddc2e80 100644 --- a/xbmc/windowing/wayland/PointerProcessor.cpp +++ b/xbmc/windowing/wayland/PointerProcessor.cpp @@ -20,9 +20,6 @@ #include #include -#include "DllWaylandClient.h" -#include "DllXKBCommon.h" - #include "CursorManager.h" #include "EventListener.h" #include "Pointer.h" diff --git a/xbmc/windowing/wayland/Region.cpp b/xbmc/windowing/wayland/Region.cpp index e77ec0ec308b5..34cfe32b957de 100644 --- a/xbmc/windowing/wayland/Region.cpp +++ b/xbmc/windowing/wayland/Region.cpp @@ -19,26 +19,18 @@ */ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Region.h" namespace xw = xbmc::wayland; -xw::Region::Region(IDllWaylandClient &clientLibrary, - struct wl_region *region) : - m_clientLibrary(clientLibrary), +xw::Region::Region(struct wl_region *region) : m_region(region) { } xw::Region::~Region() { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_region, - WL_REGION_DESTROY); - protocol::DestroyWaylandObject(m_clientLibrary, - m_region); + wl_region_destroy(m_region); } struct wl_region * @@ -53,11 +45,5 @@ xw::Region::AddRectangle(int32_t x, int32_t width, int32_t height) { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_region, - WL_REGION_ADD, - x, - y, - width, - height); + wl_region_add(m_region, x, y, width, height); } diff --git a/xbmc/windowing/wayland/Region.h b/xbmc/windowing/wayland/Region.h index 60629c6908a0c..3029962e2d67a 100644 --- a/xbmc/windowing/wayland/Region.h +++ b/xbmc/windowing/wayland/Region.h @@ -20,8 +20,6 @@ * */ -class IDllWaylandClient; - struct wl_region; namespace xbmc @@ -32,8 +30,7 @@ class Region { public: - Region(IDllWaylandClient &clientLibrary, - struct wl_region *); + explicit Region(struct wl_region *); ~Region(); Region(const Region &) = delete; @@ -48,7 +45,6 @@ class Region private: - IDllWaylandClient &m_clientLibrary; struct wl_region *m_region; }; } diff --git a/xbmc/windowing/wayland/Registry.cpp b/xbmc/windowing/wayland/Registry.cpp index 07869aac37e5e..ead9e1ffcb777 100644 --- a/xbmc/windowing/wayland/Registry.cpp +++ b/xbmc/windowing/wayland/Registry.cpp @@ -19,8 +19,6 @@ */ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Registry.h" namespace xw = xbmc::wayland; @@ -70,48 +68,30 @@ std::unique_ptr xw::ExtraWaylandGlobals::m_instance; * in the interface and wants to bind to it. This is particularly * useful for testing purposes where custom objects on the compositor * side are used. */ -xw::Registry::Registry(IDllWaylandClient &clientLibrary, - struct wl_display *display, +xw::Registry::Registry(struct wl_display *display, IWaylandRegistration ®istration) : - m_clientLibrary(clientLibrary), - m_registry(protocol::CreateWaylandObject (m_clientLibrary, - display, - m_clientLibrary.Get_wl_registry_interface())), + m_registry(wl_display_get_registry(display)), m_registration(registration) { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - display, - WL_DISPLAY_GET_REGISTRY, - m_registry); - protocol::AddListenerOnWaylandObject(m_clientLibrary, - m_registry, - &m_listener, - reinterpret_cast(this)); + wl_registry_add_listener(m_registry, &m_listener, + reinterpret_cast(this)); } xw::Registry::~Registry() { - protocol::DestroyWaylandObject(m_clientLibrary, m_registry); + wl_registry_destroy(m_registry); } /* Once a global becomes available, we immediately bind to it here * and then notify the injected listener interface that the global * is available on a named object. This allows that interface to * respond to the arrival of the new global how it wishes */ -void +void * xw::Registry::BindInternal(uint32_t name, - const char *interface, - uint32_t version, - void *proxy) + const struct wl_interface *interface, + uint32_t version) { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_registry, - WL_REGISTRY_BIND, - name, - interface, - version, - proxy); + return wl_registry_bind(m_registry, name, interface, version); } void diff --git a/xbmc/windowing/wayland/Registry.h b/xbmc/windowing/wayland/Registry.h index 53f0275f4081d..30abe3f656131 100644 --- a/xbmc/windowing/wayland/Registry.h +++ b/xbmc/windowing/wayland/Registry.h @@ -25,10 +25,6 @@ #include -#include "WaylandProtocol.h" - -class IDllWaylandClient; - namespace xbmc { namespace wayland @@ -74,8 +70,7 @@ class Registry { public: - Registry(IDllWaylandClient &clientLibrary, - struct wl_display *display, + Registry(struct wl_display *display, IWaylandRegistration ®istration); ~Registry(); @@ -86,23 +81,13 @@ class Registry template Create Bind(uint32_t name, - struct wl_interface **interface, + const struct wl_interface *interface, uint32_t version) { - Create object = - protocol::CreateWaylandObject(m_clientLibrary, - m_registry, - interface); - - /* This looks a bit funky - but it is correct. The dll returns - * a ** to wl_interface when it is in fact just a pointer to - * the static variable, so we need to remove one indirection */ - BindInternal(name, - reinterpret_cast(interface)->name, - version, - object); - return object; + void *object = BindInternal(name, + interface, + version); + return reinterpret_cast(object); } private: @@ -114,12 +99,10 @@ class Registry static void HandleRemoveGlobalCallback(void *, struct wl_registry *, uint32_t name); - void BindInternal(uint32_t name, - const char *interface, - uint32_t version, - void *proxy); + void *BindInternal(uint32_t name, + const struct wl_interface *interface, + uint32_t version); - IDllWaylandClient &m_clientLibrary; struct wl_registry *m_registry; IWaylandRegistration &m_registration; diff --git a/xbmc/windowing/wayland/Seat.cpp b/xbmc/windowing/wayland/Seat.cpp index 5580ac8137347..69baa094e2490 100644 --- a/xbmc/windowing/wayland/Seat.cpp +++ b/xbmc/windowing/wayland/Seat.cpp @@ -23,8 +23,6 @@ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Seat.h" namespace xw = xbmc::wayland; @@ -36,24 +34,18 @@ const struct wl_seat_listener xw::Seat::m_listener = Seat::HandleCapabilitiesCallback }; -xw::Seat::Seat(IDllWaylandClient &clientLibrary, - struct wl_seat *seat, +xw::Seat::Seat(struct wl_seat *seat, IInputReceiver &reciever) : - m_clientLibrary(clientLibrary), m_seat(seat), m_input(reciever), m_currentCapabilities(static_cast(0)) { - protocol::AddListenerOnWaylandObject(m_clientLibrary, - m_seat, - &m_listener, - reinterpret_cast(this)); + wl_seat_add_listener(m_seat, &m_listener, reinterpret_cast(this)); } xw::Seat::~Seat() { - protocol::DestroyWaylandObject(m_clientLibrary, - m_seat); + wl_seat_destroy(m_seat); } void xw::Seat::HandleCapabilitiesCallback(void *data, @@ -76,30 +68,12 @@ void xw::Seat::HandleCapabilities(enum wl_seat_capability cap) if (newCaps & WL_SEAT_CAPABILITY_POINTER) { - struct wl_pointer *pointer = - protocol::CreateWaylandObject(m_clientLibrary, - m_seat, - m_clientLibrary.Get_wl_pointer_interface()); - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_seat, - WL_SEAT_GET_POINTER, - pointer); - m_input.InsertPointer(pointer); + m_input.InsertPointer(wl_seat_get_pointer(m_seat)); } if (newCaps & WL_SEAT_CAPABILITY_KEYBOARD) { - struct wl_keyboard *keyboard = - protocol::CreateWaylandObject(m_clientLibrary, - m_seat, - m_clientLibrary.Get_wl_keyboard_interface()); - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_seat, - WL_SEAT_GET_KEYBOARD, - keyboard); - m_input.InsertKeyboard(keyboard); + m_input.InsertKeyboard(wl_seat_get_keyboard(m_seat)); } if (lostCaps & WL_SEAT_CAPABILITY_POINTER) diff --git a/xbmc/windowing/wayland/Seat.h b/xbmc/windowing/wayland/Seat.h index e74da006c0c86..07e30606a6be6 100644 --- a/xbmc/windowing/wayland/Seat.h +++ b/xbmc/windowing/wayland/Seat.h @@ -21,8 +21,6 @@ */ #include -class IDllWaylandClient; - namespace xbmc { namespace wayland @@ -44,8 +42,7 @@ class Seat { public: - Seat(IDllWaylandClient &, - struct wl_seat *, + Seat(struct wl_seat *, IInputReceiver &); ~Seat(); @@ -64,7 +61,6 @@ class Seat void HandleCapabilities(enum wl_seat_capability); - IDllWaylandClient &m_clientLibrary; struct wl_seat * m_seat; IInputReceiver &m_input; diff --git a/xbmc/windowing/wayland/Shell.cpp b/xbmc/windowing/wayland/Shell.cpp index 9655f0d9a818b..f804c0b80c502 100644 --- a/xbmc/windowing/wayland/Shell.cpp +++ b/xbmc/windowing/wayland/Shell.cpp @@ -19,23 +19,18 @@ */ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Shell.h" namespace xw = xbmc::wayland; -xw::Shell::Shell(IDllWaylandClient &clientLibrary, - struct wl_shell *shell) : - m_clientLibrary(clientLibrary), +xw::Shell::Shell(struct wl_shell *shell) : m_shell(shell) { } xw::Shell::~Shell() { - protocol::DestroyWaylandObject(m_clientLibrary, - m_shell); + wl_shell_destroy(m_shell); } struct wl_shell * @@ -47,15 +42,5 @@ xw::Shell::GetWlShell() struct wl_shell_surface * xw::Shell::CreateShellSurface(struct wl_surface *surface) { - struct wl_shell_surface *shellSurface = - protocol::CreateWaylandObject(m_clientLibrary, - m_shell, - m_clientLibrary.Get_wl_shell_surface_interface ()); - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_shell, - WL_SHELL_GET_SHELL_SURFACE, - shellSurface, - surface); - return shellSurface; + return wl_shell_get_shell_surface(m_shell, surface); } diff --git a/xbmc/windowing/wayland/Shell.h b/xbmc/windowing/wayland/Shell.h index 8cc7911ab6628..b901268a81ee2 100644 --- a/xbmc/windowing/wayland/Shell.h +++ b/xbmc/windowing/wayland/Shell.h @@ -20,8 +20,6 @@ * */ -class IDllWaylandClient; - struct wl_shell; struct wl_shell_surface; struct wl_surface; @@ -34,8 +32,7 @@ class Shell { public: - Shell(IDllWaylandClient &clientLibrary, - struct wl_shell *shell); + explicit Shell(struct wl_shell *shell); ~Shell(); Shell(const Shell &) = delete; @@ -46,7 +43,6 @@ class Shell private: - IDllWaylandClient &m_clientLibrary; struct wl_shell *m_shell; }; } diff --git a/xbmc/windowing/wayland/ShellSurface.cpp b/xbmc/windowing/wayland/ShellSurface.cpp index 979d8025a73e3..6713acf056d6a 100644 --- a/xbmc/windowing/wayland/ShellSurface.cpp +++ b/xbmc/windowing/wayland/ShellSurface.cpp @@ -19,8 +19,6 @@ */ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "ShellSurface.h" namespace xw = xbmc::wayland; @@ -32,20 +30,16 @@ const wl_shell_surface_listener xw::ShellSurface::m_listener = ShellSurface::HandlePopupDoneCallback }; -xw::ShellSurface::ShellSurface(IDllWaylandClient &clientLibrary, - struct wl_shell_surface *shell_surface) : - m_clientLibrary(clientLibrary), +xw::ShellSurface::ShellSurface(struct wl_shell_surface *shell_surface) : m_shellSurface(shell_surface) { - protocol::AddListenerOnWaylandObject(m_clientLibrary, - m_shellSurface, - &m_listener, - reinterpret_cast(this)); + wl_shell_surface_add_listener(m_shellSurface, &m_listener, + reinterpret_cast(this)); } xw::ShellSurface::~ShellSurface() { - protocol::DestroyWaylandObject(m_clientLibrary, m_shellSurface); + wl_shell_surface_destroy(m_shellSurface); } struct wl_shell_surface * @@ -59,12 +53,10 @@ xw::ShellSurface::SetFullscreen(enum wl_shell_surface_fullscreen_method method, uint32_t framerate, struct wl_output *output) { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_shellSurface, - WL_SHELL_SURFACE_SET_FULLSCREEN, - method, - framerate, - output); + wl_shell_surface_set_fullscreen(m_shellSurface, + method, + framerate, + output); } void @@ -97,10 +89,7 @@ xw::ShellSurface::HandlePopupDoneCallback(void *data, void xw::ShellSurface::HandlePing(uint32_t serial) { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_shellSurface, - WL_SHELL_SURFACE_PONG, - serial); + wl_shell_surface_pong(m_shellSurface, serial); } void diff --git a/xbmc/windowing/wayland/ShellSurface.h b/xbmc/windowing/wayland/ShellSurface.h index 48acbac639274..0ee1c14518239 100644 --- a/xbmc/windowing/wayland/ShellSurface.h +++ b/xbmc/windowing/wayland/ShellSurface.h @@ -21,8 +21,6 @@ */ #include -class IDllWaylandClient; - namespace xbmc { namespace wayland @@ -31,8 +29,7 @@ class ShellSurface { public: - ShellSurface(IDllWaylandClient &clientLibrary, - struct wl_shell_surface *shellSurface); + explicit ShellSurface(struct wl_shell_surface *shellSurface); ~ShellSurface(); ShellSurface(const ShellSurface &) = delete; @@ -64,7 +61,6 @@ class ShellSurface int32_t height); void HandlePopupDone(); - IDllWaylandClient &m_clientLibrary; struct wl_shell_surface *m_shellSurface; }; } diff --git a/xbmc/windowing/wayland/Surface.cpp b/xbmc/windowing/wayland/Surface.cpp index 18933b2bb556e..a5db51f78ed8b 100644 --- a/xbmc/windowing/wayland/Surface.cpp +++ b/xbmc/windowing/wayland/Surface.cpp @@ -19,8 +19,6 @@ */ #include -#include "DllWaylandClient.h" -#include "WaylandProtocol.h" #include "Surface.h" namespace xw = xbmc::wayland; @@ -49,9 +47,7 @@ xw::WaylandSurfaceListener::SurfaceCreated(xw::Surface &surface) m_handler(surface); } -xw::Surface::Surface(IDllWaylandClient &clientLibrary, - struct wl_surface *surface) : - m_clientLibrary(clientLibrary), +xw::Surface::Surface(struct wl_surface *surface) : m_surface(surface) { WaylandSurfaceListener::GetInstance().SurfaceCreated(*this); @@ -59,11 +55,7 @@ xw::Surface::Surface(IDllWaylandClient &clientLibrary, xw::Surface::~Surface() { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_surface, - WL_SURFACE_DESTROY); - protocol::DestroyWaylandObject(m_clientLibrary, - m_surface); + wl_surface_destroy(m_surface); } struct wl_surface * @@ -75,30 +67,17 @@ xw::Surface::GetWlSurface() struct wl_callback * xw::Surface::CreateFrameCallback() { - struct wl_callback *callback = - protocol::CreateWaylandObject(m_clientLibrary, - m_surface, - m_clientLibrary.Get_wl_callback_interface()); - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_surface, - WL_SURFACE_FRAME, callback); - return callback; + return wl_surface_frame(m_surface); } void xw::Surface::SetOpaqueRegion(struct wl_region *region) { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_surface, - WL_SURFACE_SET_OPAQUE_REGION, - region); + wl_surface_set_opaque_region(m_surface, region); } void xw::Surface::Commit() { - protocol::CallMethodOnWaylandObject(m_clientLibrary, - m_surface, - WL_SURFACE_COMMIT); + wl_surface_commit(m_surface); } diff --git a/xbmc/windowing/wayland/Surface.h b/xbmc/windowing/wayland/Surface.h index 090b0159fd325..195bb973c80e0 100644 --- a/xbmc/windowing/wayland/Surface.h +++ b/xbmc/windowing/wayland/Surface.h @@ -26,8 +26,6 @@ struct wl_surface; struct wl_callback; struct wl_region; -class IDllWaylandClient; - namespace xbmc { namespace wayland @@ -36,8 +34,7 @@ class Surface { public: - Surface(IDllWaylandClient &clientLibrary, - struct wl_surface *surface); + explicit Surface(struct wl_surface *surface); ~Surface(); Surface(const Surface &) = delete; @@ -50,7 +47,6 @@ class Surface private: - IDllWaylandClient &m_clientLibrary; struct wl_surface *m_surface; }; diff --git a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp deleted file mode 100644 index a2700e09195c9..0000000000000 --- a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2005-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include -#include - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include "DllWaylandClient.h" -#include "utils/log.h" - -#include "Wayland11EventQueueStrategy.h" - -namespace xwe = xbmc::wayland::events; -namespace xw11 = xbmc::wayland::version_11; - -/* It is very important that these functions occurr in the order. - * that they are written below. Deadlocks might occurr otherwise. - * - * The first function dispatches any pending events that have been - * determined from prior reads of the event queue without *also* - * reading the event queue. - * - * The second function function reads the input buffer and dispatches - * any events that occurred, but only after the reading thread goes - * to sleep waiting for new data to arrive on the pipe. - * - * The output buffer will be flushed periodically (on the render loop, - * which never sleeps) and will flush any pending requests after - * eglSwapBuffers that may have happened just before this thread starts - * polling. - * - * If the functions are not called in this order, you might run into - * a situation where pending-dispatch events might have generated a - * write to the event queue in order to keep us awake (frame events - * are a particular culprit here), or where events that we need to - * dispatch in order to keep going are never read. - */ -namespace -{ -void DispatchPendingEvents(IDllWaylandClient &clientLibrary, - struct wl_display *display) -{ - clientLibrary.wl_display_dispatch_pending(display); - /* We flush the output queue in the main thread as that needs to - * happen after eglSwapBuffers */ -} - -void ReadAndDispatch(IDllWaylandClient &clientLibrary, - struct wl_display *display) -{ - clientLibrary.wl_display_dispatch(display); -} -} - -xw11::EventQueueStrategy::EventQueueStrategy(IDllWaylandClient &clientLibrary, - struct wl_display *display) : - m_clientLibrary(clientLibrary), - m_display(display), - m_thread(std::bind(ReadAndDispatch, - std::ref(m_clientLibrary), - m_display), - std::bind(DispatchPendingEvents, - std::ref(m_clientLibrary), - m_display), - m_clientLibrary.wl_display_get_fd(m_display)) -{ -} - -namespace -{ -void ExecuteAction(const xwe::IEventQueueStrategy::Action &action) -{ - action(); -} -} - -void -xw11::EventQueueStrategy::DispatchEventsFromMain() -{ - unsigned int numActions = 0; - std::vector pendingActions; - - /* We only need to hold the lock while we copy out actions from the - * queue */ - { - CSingleLock lock(m_actionsMutex); - numActions = m_actions.size(); - pendingActions.reserve(numActions); - - /* Only pump the initial queued event count otherwise if the UI - * keeps pushing events then the loop won't finish */ - for (unsigned int index = 0; index < numActions; ++index) - { - pendingActions.push_back(m_actions.front()); - m_actions.pop(); - } - } - - /* Execute each of the queued up actions */ - std::for_each(pendingActions.begin(), - pendingActions.end(), - ExecuteAction); - - /* After we've done dispatching flush the event queue */ - m_clientLibrary.wl_display_flush(m_display); -} - -void -xw11::EventQueueStrategy::PushAction(const Action &action) -{ - CSingleLock lock(m_actionsMutex); - m_actions.push(action); -} diff --git a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h b/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h deleted file mode 100644 index 18914de694372..0000000000000 --- a/xbmc/windowing/wayland/Wayland11EventQueueStrategy.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2011-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include - -#include "threads/CriticalSection.h" -#include "EventQueueStrategy.h" -#include "PollThread.h" - -class IDllWaylandClient; - -struct wl_display; - -namespace xbmc -{ -namespace wayland -{ -namespace version_11 -{ -/* The EventQueueStrategy for Wayland <= 1.1 requires that events - * be dispatched and initally processed in a separate thread. This - * means that all the wayland proxy object wrappers callbacks will - * be running in the same thread that reads the event queue for events. - * - * When those events are initially processed, they will be put into the - * main WaylandEventLoop queue and dispatched sequentially from there - * periodically (once every redraw) into the main thread. - * - * The reason for this is that Wayland versions prior to 1.1 provide - * no means to read the event queue without also dispatching pending - * events and callbacks on proxy objects. But we also cannot block the - * main thread, which may occurr if we call wl_display_dispatch - * and there is no pending frame callback because our surface is not - * visible. - */ -class EventQueueStrategy : - public events::IEventQueueStrategy -{ -public: - - EventQueueStrategy(IDllWaylandClient &clientLibrary, - struct wl_display *display); - - void PushAction(const Action &action); - void DispatchEventsFromMain(); - -private: - - IDllWaylandClient &m_clientLibrary; - struct wl_display *m_display; - - events::PollThread m_thread; - - CCriticalSection m_actionsMutex; - std::queue m_actions; -}; -} -} -} diff --git a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp index 9415527f5e4f4..63224e4529b31 100644 --- a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp +++ b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.cpp @@ -23,11 +23,12 @@ #define _GNU_SOURCE #endif -#include "DllWaylandClient.h" #include "utils/log.h" #include "Wayland12EventQueueStrategy.h" +#include + namespace xw12 = xbmc::wayland::version_12; namespace @@ -38,25 +39,22 @@ void Nothing() { } -void Read(IDllWaylandClient &clientLibrary, - struct wl_display *display) +void Read(struct wl_display *display) { /* If wl_display_prepare_read() returns a nonzero value it means * that we still have more events to dispatch. So let the main thread * dispatch all the pending events first before trying to read * more events from the pipe */ - if ((*(clientLibrary.wl_display_prepare_read_proc()))(display) == 0) - (*(clientLibrary.wl_display_read_events_proc()))(display); + if (wl_display_prepare_read(display) == 0) + wl_display_read_events(display); } } -xw12::EventQueueStrategy::EventQueueStrategy(IDllWaylandClient &clientLibrary, - struct wl_display *display) : - m_clientLibrary(clientLibrary), +xw12::EventQueueStrategy::EventQueueStrategy(struct wl_display *display) : m_display(display), - m_thread(std::bind(Read, std::ref(m_clientLibrary), display), + m_thread(std::bind(Read, display), std::bind(Nothing), - m_clientLibrary.wl_display_get_fd(m_display)) + wl_display_get_fd(m_display)) { } @@ -83,10 +81,10 @@ xw12::EventQueueStrategy::DispatchEventsFromMain() * are a particular culprit here), or where events that we need to * dispatch in order to keep going are never read. */ - m_clientLibrary.wl_display_dispatch_pending(m_display); + wl_display_dispatch_pending(m_display); /* We perform the flush here and not in the reader thread * as it needs to come after eglSwapBuffers */ - m_clientLibrary.wl_display_flush(m_display); + wl_display_flush(m_display); } void diff --git a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h index 32836ff617224..d98db71823765 100644 --- a/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h +++ b/xbmc/windowing/wayland/Wayland12EventQueueStrategy.h @@ -24,8 +24,6 @@ #include "EventQueueStrategy.h" #include "PollThread.h" -class IDllWaylandClient; - struct wl_display; namespace xbmc @@ -39,15 +37,13 @@ class EventQueueStrategy : { public: - EventQueueStrategy(IDllWaylandClient &clientLibrary, - struct wl_display *display); + EventQueueStrategy(struct wl_display *display); void PushAction(const Action &action); void DispatchEventsFromMain(); private: - IDllWaylandClient &m_clientLibrary; struct wl_display *m_display; events::PollThread m_thread; diff --git a/xbmc/windowing/wayland/WaylandLibraries.cpp b/xbmc/windowing/wayland/WaylandLibraries.cpp deleted file mode 100644 index 5562635808ce6..0000000000000 --- a/xbmc/windowing/wayland/WaylandLibraries.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include -#include - -#include -#include "WaylandLibraries.h" - -namespace xw = xbmc::wayland; - -void -xw::LoadLibrary(DllDynamic &dll) -{ - if (!dll.Load()) - { - std::stringstream ss; - ss << "Failed to load library " - << dll.GetFile().c_str(); - - throw std::runtime_error(ss.str()); - } -} - -IDllWaylandClient & -xw::Libraries::ClientLibrary() -{ - return m_clientLibrary.Get(); -} - -IDllWaylandEGL & -xw::Libraries::EGLLibrary() -{ - return m_eglLibrary.Get(); -} - -IDllXKBCommon & -xw::Libraries::XKBCommonLibrary() -{ - return m_xkbCommonLibrary.Get(); -} diff --git a/xbmc/windowing/wayland/WaylandLibraries.h b/xbmc/windowing/wayland/WaylandLibraries.h deleted file mode 100644 index 8b6ea52e61f77..0000000000000 --- a/xbmc/windowing/wayland/WaylandLibraries.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2011-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include "DllWaylandClient.h" -#include "DllWaylandEgl.h" -#include "DllXKBCommon.h" - -namespace xbmc -{ -namespace wayland -{ -template -class AutoloadDll -{ - public: - - AutoloadDll(); - ~AutoloadDll(); - - AutoloadDll(const AutoloadDll &) = delete; - AutoloadDll &operator=(const AutoloadDll &) = delete; - - DllInterface & Get(); - - private: - - Dll m_dll; -}; - -class Libraries -{ -public: - - Libraries() = default; - - Libraries(const Libraries &) = delete; - Libraries &operator=(const Libraries &) = delete; - - IDllWaylandClient & ClientLibrary(); - IDllWaylandEGL & EGLLibrary(); - IDllXKBCommon & XKBCommonLibrary(); - -private: - - AutoloadDll m_clientLibrary; - AutoloadDll m_eglLibrary; - AutoloadDll m_xkbCommonLibrary; -}; - -void LoadLibrary(DllDynamic &dll); - -template -AutoloadDll::AutoloadDll() -{ - LoadLibrary(m_dll); -} - -template -DllInterface & -AutoloadDll::Get() -{ - return m_dll; -} - -template -AutoloadDll::~AutoloadDll() -{ - m_dll.Unload(); -} -} -} diff --git a/xbmc/windowing/wayland/WaylandProtocol.h b/xbmc/windowing/wayland/WaylandProtocol.h deleted file mode 100644 index 945b63f99a8e5..0000000000000 --- a/xbmc/windowing/wayland/WaylandProtocol.h +++ /dev/null @@ -1,244 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2005-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include -#include -#include - -#include "DllWaylandClient.h" - -/* These functions are wrappers around using the wayland protocol - * directly. Unfortunately, since most of the protocol has autogenerated - * binding code, and that binding code assumes that we're directly - * linked to the client library (we're not), we can't use it. So - * we need to use wl_proxy_create, wl_proxy_marshal and wl_proxy_destory - * directly. - * - * These functions effectively exist to reduce some of the duplication - * that surrounds using these functions directly. You should look - * at the autogenerated binding code to determine how wl_proxy_marshal - * should be used to call a particular method. - * - * Also note that there may be some cases where additional constructor - * or destructor functions might need to be called before or after - * CreateWaylandObject and DestroyWaylandObject. - * - * If you need to call a method with more than six arguments, - * you'll need to add a new overload here */ -namespace xbmc -{ -namespace wayland -{ -namespace protocol -{ -/* These functions call a method on a specifed wayland object - * (you should use the pointer provided by the client library - * and not the wrapper) with the specified opcode and - * arguments. - * - * THERE IS NO TYPE CHECKING so you should be especially sure that - * you're calling it with the right arguments. Failure to do so - * will result in very strange behaviour - */ -template -void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, - Object object, - uint32_t opcode) -{ - struct wl_proxy *proxy = - reinterpret_cast(object); - clientLibrary.wl_proxy_marshaller()(proxy, - opcode); -} -template -void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, - Object object, - uint32_t opcode, - A1 arg1) -{ - struct wl_proxy *proxy = - reinterpret_cast(object); - clientLibrary.wl_proxy_marshaller()(proxy, - opcode, - arg1); -} - -template -void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, - Object object, - uint32_t opcode, - A1 arg1, - A2 arg2) -{ - struct wl_proxy *proxy = - reinterpret_cast(object); - clientLibrary.wl_proxy_marshaller()(proxy, - opcode, - arg1, - arg2); -} - -template -void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, - Object object, - uint32_t opcode, - A1 arg1, - A2 arg2, - A3 arg3) -{ - struct wl_proxy *proxy = - reinterpret_cast(object); - clientLibrary.wl_proxy_marshaller()(proxy, - opcode, - arg1, - arg2, - arg3); -} - -template -void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, - Object object, - uint32_t opcode, - A1 arg1, - A2 arg2, - A3 arg3, - A4 arg4) -{ - struct wl_proxy *proxy = - reinterpret_cast(object); - clientLibrary.wl_proxy_marshaller()(proxy, - opcode, - arg1, - arg2, - arg3, - arg4); -} - -template -void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary, - Object object, - uint32_t opcode, - A1 arg1, - A2 arg2, - A3 arg3, - A4 arg4, - A5 arg5) -{ - struct wl_proxy *proxy = - reinterpret_cast(object); - clientLibrary.wl_proxy_marshaller()(proxy, - opcode, - arg1, - arg2, - arg3, - arg4, - arg5); -} - -/* This function template returns a new unmanaged object pointer - * as specified by Create with the RPC interface as specified - * as a child in the server ownership hierarchy of factory. - * - * Create must be castable to struct wl_proxy *, which - * means that struct wl_proxy should be its first member. Generally - * all wayland library proxy objects satisfy this criteria - */ -template -Create CreateWaylandObject(IDllWaylandClient &clientLibrary, - Factory factory, - struct wl_interface **interface) -{ - struct wl_proxy *pfactory = - reinterpret_cast(factory); - struct wl_proxy *proxy = - clientLibrary.wl_proxy_create(pfactory, - reinterpret_cast(interface)); - - if (!proxy) - { - std::stringstream ss; - ss << "Failed to create " - << typeid(Create).name() - << " from factory " - << typeid(Factory).name() - << " at 0x" - << std::hex - << reinterpret_cast(pfactory) - << std::dec; - throw std::runtime_error(ss.str()); - } - - return reinterpret_cast(proxy); -} - -/* This function adds a new "listener" to the object specified. - * A "listener" is generally a struct of function pointers as specified - * by the object's RPC interface for each event it can generate. These - * can usually be found in the protocol header. "data" is passed - * to each callback to make it a full closure. */ -template -int AddListenerOnWaylandObject(IDllWaylandClient &clientLibrary, - Object object, - Listener listener, - void *data) -{ - struct wl_proxy *proxy = - reinterpret_cast(object); - - /* C-style casts are bad, but there is no equavilent to - * std::remove_const in C++98 and we are reinterpret_cast'ing - * anyways */ - IDllWaylandClient::wl_proxy_listener_func *listenerFunc = - (IDllWaylandClient::wl_proxy_listener_func *)((void *)listener); - return clientLibrary.wl_proxy_add_listener(proxy, listenerFunc, data); -} - -/* This function destroys the proxy object and releases its resources - * on the client side. There may be an additional destroy request to - * release resources on the server side. That must be called - * prior to this. */ -template -void DestroyWaylandObject(IDllWaylandClient &clientLibrary, - Object *object) -{ - struct wl_proxy *proxy = - reinterpret_cast(object); - clientLibrary.wl_proxy_destroy(proxy); -} -} -} -} diff --git a/xbmc/windowing/wayland/WinEventsWayland.cpp b/xbmc/windowing/wayland/WinEventsWayland.cpp index dc2e8d06e04b9..eb470ea78978e 100644 --- a/xbmc/windowing/wayland/WinEventsWayland.cpp +++ b/xbmc/windowing/wayland/WinEventsWayland.cpp @@ -112,17 +112,13 @@ void CWinEventsWayland::DestroyEventQueueStrategy() * object to encapsulate all of that state. When the seat goes away * we just unset the manager object and it is all cleaned up at that * point */ -void CWinEventsWayland::SetWaylandSeat(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - struct wl_seat *s) +void CWinEventsWayland::SetWaylandSeat(struct wl_seat *s) { if (!g_eventLoop.get()) throw std::logic_error("Must have a wl_display set before setting " "the wl_seat in CWinEventsWayland "); - g_inputInstance.reset(new xbmc::InputFactory(clientLibrary, - xkbCommonLibrary, - s, + g_inputInstance.reset(new xbmc::InputFactory(s, *g_eventLoop, *g_eventLoop)); } diff --git a/xbmc/windowing/wayland/WinEventsWayland.h b/xbmc/windowing/wayland/WinEventsWayland.h index 932cfd272bcf1..91136aae217b7 100644 --- a/xbmc/windowing/wayland/WinEventsWayland.h +++ b/xbmc/windowing/wayland/WinEventsWayland.h @@ -28,9 +28,6 @@ struct wl_display; struct wl_seat; struct wl_surface; -class IDllWaylandClient; -class IDllXKBCommon; - namespace xbmc { namespace wayland @@ -54,9 +51,7 @@ class CWinEventsWayland : public IWinEvents static void SetEventQueueStrategy(xbmc::wayland::events::IEventQueueStrategy &strategy); static void DestroyEventQueueStrategy(); - static void SetWaylandSeat(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - struct wl_seat *seat); + static void SetWaylandSeat(struct wl_seat *seat); static void DestroyWaylandSeat(); static void SetXBMCSurface(struct wl_surface *surf); diff --git a/xbmc/windowing/wayland/XBMCConnection.cpp b/xbmc/windowing/wayland/XBMCConnection.cpp index 46960fc71330c..08bd5e42f9403 100644 --- a/xbmc/windowing/wayland/XBMCConnection.cpp +++ b/xbmc/windowing/wayland/XBMCConnection.cpp @@ -31,9 +31,6 @@ #include "utils/StringUtils.h" -#include "DllWaylandClient.h" -#include "DllXKBCommon.h" - #include "Callback.h" #include "Compositor.h" #include "Display.h" @@ -42,10 +39,8 @@ #include "Region.h" #include "Shell.h" -#include "WaylandProtocol.h" #include "XBMCConnection.h" -#include "Wayland11EventQueueStrategy.h" #include "Wayland12EventQueueStrategy.h" namespace xbmc @@ -123,7 +118,7 @@ class WaylandGlobalObject : public: WaylandGlobalObject(uint32_t minimum, - struct wl_interface **interface) : + const struct wl_interface *interface) : GlobalInterface(), m_minimum(minimum), m_interface(interface) @@ -131,7 +126,7 @@ class WaylandGlobalObject : } WaylandGlobalObject(uint32_t minimum, - struct wl_interface **interface, + const struct wl_interface *interface, const AvailabilityHook &hook) : GlobalInterface(hook), m_minimum(minimum), @@ -144,7 +139,7 @@ class WaylandGlobalObject : private: uint32_t m_minimum; - struct wl_interface **m_interface; + const struct wl_interface *m_interface; }; /* A StoredGlobalInterface is an implementation of RemoteGlobalInterface @@ -171,7 +166,7 @@ class StoredGlobalInterface : * a wrapper class around that wayland object */ StoredGlobalInterface(const Factory &factory, uint32_t minimum, - struct wl_interface **interface) : + const struct wl_interface *interface) : m_waylandObject(minimum, interface), m_factory(factory) { @@ -179,7 +174,7 @@ class StoredGlobalInterface : StoredGlobalInterface(const Factory &factory, uint32_t minimum, - struct wl_interface **interface, + const struct wl_interface *interface, const GlobalInterface::AvailabilityHook &hook) : m_waylandObject(minimum, interface, hook), m_factory(factory) @@ -216,9 +211,7 @@ class XBMCConnection::Private : { public: - Private(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - EventInjector &eventInjector); + explicit Private(EventInjector &eventInjector); ~Private(); /* Synchronization entry point - call this function to issue a @@ -244,9 +237,6 @@ class XBMCConnection::Private : private: - IDllWaylandClient &m_clientLibrary; - IDllXKBCommon &m_xkbCommonLibrary; - EventInjector m_eventInjector; /* Do not call this from a non-main thread. The main thread may be @@ -388,22 +378,19 @@ const std::string OutputName("wl_output"); /* These are functions that satisfy the definition of a "Factory" * for the purposes of StoredGlobalInterface */ -xw::Compositor * CreateCompositor(struct wl_compositor *compositor, - IDllWaylandClient *clientLibrary) +xw::Compositor * CreateCompositor(struct wl_compositor *compositor) { - return new xw::Compositor(*clientLibrary, compositor); + return new xw::Compositor(compositor); } -xw::Output * CreateOutput(struct wl_output *output, - IDllWaylandClient *clientLibrary) +xw::Output * CreateOutput(struct wl_output *output) { - return new xw::Output(*clientLibrary, output); + return new xw::Output(output); } -xw::Shell * CreateShell(struct wl_shell *shell, - IDllWaylandClient *clientLibrary) +xw::Shell * CreateShell(struct wl_shell *shell) { - return new xw::Shell(*clientLibrary, shell); + return new xw::Shell(shell); } bool ConstructorMatchesInterface(const xw::RemoteGlobalInterface::Constructor &constructor, @@ -469,19 +456,9 @@ const unsigned int RequestedSeatVersion = 1; * and remove support for wayland versions <= 1.1. */ xwe::IEventQueueStrategy * -EventQueueForClientVersion(IDllWaylandClient &clientLibrary, - struct wl_display *display) +EventQueueForClientVersion(struct wl_display *display) { - /* TODO: Test for wl_display_read_events / wl_display_prepare_read */ - const bool version12 = - clientLibrary.wl_display_read_events_proc() && - clientLibrary.wl_display_prepare_read_proc(); - if (version12) - return new xw::version_12::EventQueueStrategy(clientLibrary, - display); - else - return new xw::version_11::EventQueueStrategy(clientLibrary, - display); + return new xw::version_12::EventQueueStrategy(display); } } @@ -504,31 +481,24 @@ EventQueueForClientVersion(IDllWaylandClient &clientLibrary, * when our wl_registry.add_listener request has finished processing * on both the server and client side */ -xw::XBMCConnection::Private::Private(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - EventInjector &eventInjector) : - m_clientLibrary(clientLibrary), - m_xkbCommonLibrary(xkbCommonLibrary), +xw::XBMCConnection::Private::Private(EventInjector &eventInjector) : m_eventInjector(eventInjector), - m_display(new xw::Display(clientLibrary)), - m_registry(new xw::Registry(clientLibrary, - m_display->GetWlDisplay(), + m_display(new xw::Display()), + m_registry(new xw::Registry(m_display->GetWlDisplay(), *this)), - m_compositor(std::bind(CreateCompositor, std::placeholders::_1, - &m_clientLibrary), + m_compositor(std::bind(CreateCompositor, std::placeholders::_1), RequestedCompositorVersion, - clientLibrary.Get_wl_compositor_interface()), - m_shell(std::bind(CreateShell, std::placeholders::_1, &m_clientLibrary), + &wl_compositor_interface), + m_shell(std::bind(CreateShell, std::placeholders::_1), RequestedShellVersion, - clientLibrary.Get_wl_shell_interface()), + &wl_shell_interface), m_seat(RequestedSeatVersion, - clientLibrary.Get_wl_seat_interface(), + &wl_seat_interface, std::bind(&Private::InjectSeat, this)), - m_outputs(std::bind(CreateOutput, std::placeholders::_1, &m_clientLibrary), + m_outputs(std::bind(CreateOutput, std::placeholders::_1), RequestedOutputVersion, - clientLibrary.Get_wl_output_interface()), - m_eventQueue(EventQueueForClientVersion(m_clientLibrary, - m_display->GetWlDisplay())) + &wl_output_interface), + m_eventQueue(EventQueueForClientVersion(m_display->GetWlDisplay())) { /* Tell CWinEvents what our event queue is. That way * CWinEvents::MessagePump is now able to dispatch events from @@ -547,9 +517,7 @@ xw::XBMCConnection::Private::InjectSeat() * know about it so that it can wrap it and query it for more * information about input devices */ struct wl_seat *seat = m_seat.FetchPending(*m_registry); - (*m_eventInjector.setWaylandSeat)(m_clientLibrary, - m_xkbCommonLibrary, - seat); + (*m_eventInjector.setWaylandSeat)(seat); } xw::XBMCConnection::Private::~Private() @@ -558,10 +526,8 @@ xw::XBMCConnection::Private::~Private() (*m_eventInjector.destroyEventQueue)(); } -xw::XBMCConnection::XBMCConnection(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - EventInjector &eventInjector) : - priv(new Private (clientLibrary, xkbCommonLibrary, eventInjector)) +xw::XBMCConnection::XBMCConnection(EventInjector &eventInjector) : + priv(new Private (eventInjector)) { } @@ -658,8 +624,7 @@ void xw::XBMCConnection::Private::WaitForSynchronize() this)); synchronized = false; - synchronizeCallback.reset(new xw::Callback(m_clientLibrary, - m_display->Sync(), + synchronizeCallback.reset(new xw::Callback(m_display->Sync(), func)); /* For version 1.1 event queues the effect of this is going to be diff --git a/xbmc/windowing/wayland/XBMCConnection.h b/xbmc/windowing/wayland/XBMCConnection.h index ca6dccb641b2b..ef7606247fea9 100644 --- a/xbmc/windowing/wayland/XBMCConnection.h +++ b/xbmc/windowing/wayland/XBMCConnection.h @@ -21,9 +21,6 @@ */ #include -class IDllWaylandClient; -class IDllXKBCommon; - struct wl_compositor; struct wl_display; struct wl_output; @@ -55,9 +52,7 @@ class XBMCConnection { typedef void (*SetEventQueue)(events::IEventQueueStrategy &strategy); typedef void (*DestroyEventQueue)(); - typedef void (*SetWaylandSeat)(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - struct wl_seat *seat); + typedef void (*SetWaylandSeat)(struct wl_seat *seat); typedef void (*DestroyWaylandSeat)(); typedef bool (*MessagePump)(); @@ -68,9 +63,7 @@ class XBMCConnection MessagePump messagePump; }; - XBMCConnection(IDllWaylandClient &clientLibrary, - IDllXKBCommon &xkbCommonLibrary, - EventInjector &injector); + XBMCConnection(EventInjector &injector); ~XBMCConnection(); void PreferredResolution(RESOLUTION_INFO &res) const; diff --git a/xbmc/windowing/wayland/XBMCSurface.cpp b/xbmc/windowing/wayland/XBMCSurface.cpp index acfbbb7f43ae8..ad2afe3ce9c18 100644 --- a/xbmc/windowing/wayland/XBMCSurface.cpp +++ b/xbmc/windowing/wayland/XBMCSurface.cpp @@ -24,9 +24,6 @@ #include -#include "DllWaylandClient.h" -#include "DllWaylandEgl.h" - #include "Callback.h" #include "Compositor.h" #include "OpenGLSurface.h" @@ -36,7 +33,6 @@ #include "ShellSurface.h" #include "Surface.h" -#include "WaylandProtocol.h" #include "XBMCSurface.h" namespace xbmc @@ -47,18 +43,13 @@ class XBMCSurface::Private { public: - Private(IDllWaylandClient &clientLibrary, - IDllWaylandEGL &eglLibrary, - const EventInjector &eventInjector, + Private(const EventInjector &eventInjector, Compositor &compositor, Shell &shell, uint32_t width, uint32_t height); typedef std::function RegionFactory; - - IDllWaylandClient &m_clientLibrary; - IDllWaylandEGL &m_eglLibrary; EventInjector m_eventInjector; @@ -90,27 +81,20 @@ namespace xw = xbmc::wayland; * as std::runtime_errors and the object that creates this one * needs to handle catching them. */ -xw::XBMCSurface::Private::Private(IDllWaylandClient &clientLibrary, - IDllWaylandEGL &eglLibrary, - const EventInjector &eventInjector, +xw::XBMCSurface::Private::Private(const EventInjector &eventInjector, Compositor &compositor, Shell &shell, uint32_t width, uint32_t height) : - m_clientLibrary(clientLibrary), - m_eglLibrary(eglLibrary), m_eventInjector(eventInjector), m_regionFactory(std::bind(&Compositor::CreateRegion, &compositor)), - m_surface(new xw::Surface(m_clientLibrary, - compositor.CreateSurface())), - m_shellSurface(new xw::ShellSurface(m_clientLibrary, - shell.CreateShellSurface( + m_surface(new xw::Surface(compositor.CreateSurface())), + m_shellSurface(new xw::ShellSurface(shell.CreateShellSurface( m_surface->GetWlSurface()))), /* Creating a new xbmc::wayland::OpenGLSurface will manage the * attach-and-commit process on eglSwapBuffers */ - m_glSurface(new xw::OpenGLSurface(m_eglLibrary, - m_surface->GetWlSurface(), + m_glSurface(new xw::OpenGLSurface(m_surface->GetWlSurface(), width, height)) { @@ -121,7 +105,7 @@ xw::XBMCSurface::Private::Private(IDllWaylandClient &clientLibrary, * speedup, especially for larger surfaces. It also means that * this window can be placed in an overlay plane, so it can * skip compositing alltogether */ - xw::Region region(m_clientLibrary, m_regionFactory()); + xw::Region region(m_regionFactory()); region.AddRectangle(0, 0, 640, 480); @@ -139,16 +123,12 @@ xw::XBMCSurface::Private::Private(IDllWaylandClient &clientLibrary, (*m_eventInjector.setXBMCSurface)(m_surface->GetWlSurface()); } -xw::XBMCSurface::XBMCSurface(IDllWaylandClient &clientLibrary, - IDllWaylandEGL &eglLibrary, - const EventInjector &eventInjector, +xw::XBMCSurface::XBMCSurface(const EventInjector &eventInjector, Compositor &compositor, Shell &shell, uint32_t width, uint32_t height) : - priv(new Private(clientLibrary, - eglLibrary, - eventInjector, + priv(new Private(eventInjector, compositor, shell, width, @@ -185,8 +165,7 @@ xw::XBMCSurface::Resize(uint32_t width, uint32_t height) * opaque region must also change */ priv->m_glSurface->Resize(width, height); - xw::Region region(priv->m_clientLibrary, - priv->m_regionFactory()); + xw::Region region(priv->m_regionFactory()); region.AddRectangle(0, 0, width, height); @@ -207,8 +186,7 @@ void xw::XBMCSurface::Private::OnFrameCallback(uint32_t time) void xw::XBMCSurface::Private::AddFrameCallback() { - m_frameCallback.reset(new xw::Callback(m_clientLibrary, - m_surface->CreateFrameCallback(), + m_frameCallback.reset(new xw::Callback(m_surface->CreateFrameCallback(), std::bind(&Private::OnFrameCallback, this, std::placeholders::_1))); diff --git a/xbmc/windowing/wayland/XBMCSurface.h b/xbmc/windowing/wayland/XBMCSurface.h index a9228d6b1002d..ad6d966f5875a 100644 --- a/xbmc/windowing/wayland/XBMCSurface.h +++ b/xbmc/windowing/wayland/XBMCSurface.h @@ -20,9 +20,6 @@ * */ -class IDllWaylandClient; -class IDllWaylandEGL; - struct wl_region; typedef struct wl_egl_window * EGLNativeWindowType; @@ -50,9 +47,7 @@ class XBMCSurface SetXBMCSurface setXBMCSurface; }; - XBMCSurface(IDllWaylandClient &clientLibrary, - IDllWaylandEGL &eglLibrary, - const EventInjector &eventInjector, + XBMCSurface(const EventInjector &eventInjector, Compositor &compositor, Shell &shell, uint32_t width, From 33b3ff78b8591c72bfde5ce9a479045797f96e7f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 46/59] windowing/wayland/Display: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/Display.cpp | 32 ------------------------------ xbmc/windowing/wayland/Display.h | 29 +++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/xbmc/windowing/wayland/Display.cpp b/xbmc/windowing/wayland/Display.cpp index e4a9456743797..8443ac484fd76 100644 --- a/xbmc/windowing/wayland/Display.cpp +++ b/xbmc/windowing/wayland/Display.cpp @@ -23,18 +23,10 @@ #include -#include - #include "Display.h" namespace xw = xbmc::wayland; -void -xw::WaylandDisplayListener::SetHandler(const Handler &handler) -{ - m_handler = handler; -} - void xw::WaylandDisplayListener::DisplayAvailable(Display &display) { @@ -76,27 +68,3 @@ xw::Display::~Display() wl_display_flush(m_display); wl_display_disconnect(m_display); } - -struct wl_display * -xw::Display::GetWlDisplay() -{ - return m_display; -} - -EGLNativeDisplayType * -xw::Display::GetEGLNativeDisplay() -{ - return &m_display; -} - -/* Create a sync callback object. This can be wrapped in an - * xbmc::wayland::Callback object to call an arbitrary function - * as soon as the display has finished processing all commands. - * - * This does not block until a synchronization is complete - - * consider using a function like WaitForSynchronize to do that */ -struct wl_callback * -xw::Display::Sync() -{ - return wl_display_sync(m_display); -} diff --git a/xbmc/windowing/wayland/Display.h b/xbmc/windowing/wayland/Display.h index bc403a654a42b..a66a0f1973c3a 100644 --- a/xbmc/windowing/wayland/Display.h +++ b/xbmc/windowing/wayland/Display.h @@ -19,6 +19,9 @@ * . * */ + +#include + #include #include @@ -41,9 +44,24 @@ class Display Display(const Display &) = delete; Display &operator=(const Display &) = delete; - struct wl_display * GetWlDisplay(); - EGLNativeDisplayType* GetEGLNativeDisplay(); - struct wl_callback * Sync(); + struct wl_display * GetWlDisplay() { + return m_display; + } + + EGLNativeDisplayType* GetEGLNativeDisplay() { + return &m_display; + } + + /* Create a sync callback object. This can be wrapped in an + * xbmc::wayland::Callback object to call an arbitrary function + * as soon as the display has finished processing all commands. + * + * This does not block until a synchronization is complete - + * consider using a function like WaitForSynchronize to do that + */ + struct wl_callback * Sync() { + return wl_display_sync(m_display); + } private: @@ -59,7 +77,10 @@ class WaylandDisplayListener typedef std::function Handler; - void SetHandler(const Handler &); + void SetHandler(const Handler &handler) { + m_handler = handler; + } + void DisplayAvailable(Display &); static WaylandDisplayListener & GetInstance(); From 196862d60c8c8475c0078792b9079370393cf2dc Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 47/59] windowing/wayland/Callback: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/Callback.cpp | 12 ------------ xbmc/windowing/wayland/Callback.h | 8 ++++++-- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/xbmc/windowing/wayland/Callback.cpp b/xbmc/windowing/wayland/Callback.cpp index 2c729077bef58..f7974d4d0a878 100644 --- a/xbmc/windowing/wayland/Callback.cpp +++ b/xbmc/windowing/wayland/Callback.cpp @@ -17,7 +17,6 @@ * . * */ -#include #include "Callback.h" @@ -37,17 +36,6 @@ xw::Callback::Callback(struct wl_callback *callback, reinterpret_cast(this)); } -xw::Callback::~Callback() -{ - wl_callback_destroy(m_callback); -} - -struct wl_callback * -xw::Callback::GetWlCallback() -{ - return m_callback; -} - void xw::Callback::OnCallback(void *data, struct wl_callback *callback, diff --git a/xbmc/windowing/wayland/Callback.h b/xbmc/windowing/wayland/Callback.h index a36a89c6d3eb0..fd8aab2ec8d48 100644 --- a/xbmc/windowing/wayland/Callback.h +++ b/xbmc/windowing/wayland/Callback.h @@ -40,12 +40,16 @@ class Callback Callback(struct wl_callback *callback, const Func &func); - ~Callback(); + ~Callback() { + wl_callback_destroy(m_callback); + } Callback(const Callback &) = delete; Callback &operator=(const Callback &) = delete; - struct wl_callback * GetWlCallback(); + struct wl_callback * GetWlCallback() { + return m_callback; + } static const struct wl_callback_listener m_listener; From 99dd5cc8472a41ee0e6a35e4331d3b7af19bda39 Mon Sep 17 00:00:00 2001 From: memeka Date: Mon, 9 Oct 2017 13:29:51 +1030 Subject: [PATCH 48/59] Wayland: cmake rules --- project/cmake/CMakeLists.txt | 10 +++- project/cmake/modules/FindWayland.cmake | 44 +++++++++++++++ .../treedata/optional/common/wayland.txt | 1 + xbmc/windowing/wayland/CMakeLists.txt | 55 +++++++++++++++++++ 4 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 project/cmake/modules/FindWayland.cmake create mode 100644 project/cmake/treedata/optional/common/wayland.txt create mode 100644 xbmc/windowing/wayland/CMakeLists.txt diff --git a/project/cmake/CMakeLists.txt b/project/cmake/CMakeLists.txt index 63af695e16d64..ee20e6af669f3 100644 --- a/project/cmake/CMakeLists.txt +++ b/project/cmake/CMakeLists.txt @@ -52,6 +52,7 @@ if(UNIX) option(ENABLE_INTERNAL_CROSSGUID "Enable internal crossguid?" ON) option(ENABLE_OPENSSL "Enable OpenSSL?" ON) option(ENABLE_SDL "Enable SDL?" OFF) + option(ENABLE_WAYLAND "Enable Wayland?" OFF) if(CORE_SYSTEM_NAME STREQUAL linux OR CORE_SYSTEM_NAME STREQUAL freebsd) option(ENABLE_X11 "Enable X11 support?" ON) option(ENABLE_AML "Enable AML?" OFF) @@ -206,8 +207,13 @@ if(NOT WIN32) else() core_optional_dep(OpenGLES) if(OPENGLES_FOUND) - core_optional_dep(X ENABLE_X11) - core_optional_dep(LibDRM ENABLE_X11) + if (ENABLE_WAYLAND) + core_require_dep(Wayland ENABLE_WAYLAND) + core_optional_dep(LibDRM ENABLE_WAYLAND) + else() + core_optional_dep(X ENABLE_X11) + core_optional_dep(LibDRM ENABLE_X11) + endif() endif() endif() if(NOT APPLE) diff --git a/project/cmake/modules/FindWayland.cmake b/project/cmake/modules/FindWayland.cmake new file mode 100644 index 0000000000000..27bd08ffbbb9a --- /dev/null +++ b/project/cmake/modules/FindWayland.cmake @@ -0,0 +1,44 @@ +#.rst: +# FindWayland +# ----------- +# Finds the Wayland library +# +# This will will define the following variables:: +# +# WAYLAND_FOUND - the system has Wayland +# WAYLAND_INCLUDE_DIRS - the Wayland include directory +# WAYLAND_LIBRARIES - the Wayland libraries +# WAYLAND_DEFINITIONS - the Wayland definitions + + +if(PKG_CONFIG_FOUND) + pkg_check_modules (PC_WAYLAND wayland-client wayland-egl xkbcommon QUIET) +endif() + +find_path(WAYLAND_INCLUDE_DIR NAMES wayland-client.h + PATHS ${PC_WAYLAND_INCLUDE_DIRS}) + +find_library(WAYLAND_CLIENT_LIBRARY NAMES wayland-client + PATHS ${PC_WAYLAND_LIBRARIES} ${PC_WAYLAND_LIBRARY_DIRS}) + +find_library(WAYLAND_EGL_LIBRARY NAMES wayland-egl + PATHS ${PC_WAYLAND_LIBRARIES} ${PC_WAYLAND_LIBRARY_DIRS}) + +find_library(XKBCOMMON_LIBRARY NAMES xkbcommon + PATHS ${PC_WAYLAND_LIBRARIES} ${PC_WAYLAND_LIBRARY_DIRS}) + +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (WAYLAND + REQUIRED_VARS + WAYLAND_INCLUDE_DIR + WAYLAND_CLIENT_LIBRARY + WAYLAND_EGL_LIBRARY + XKBCOMMON_LIBRARY) + +if (WAYLAND_FOUND) + set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARY} ${WAYLAND_EGL_LIBRARY} ${XKBCOMMON_LIBRARY}) + set(WAYLAND_INCLUDE_DIRS ${PC_WAYLAND_INCLUDE_DIRS}) + set(WAYLAND_DEFINITIONS -DHAVE_WAYLAND=1) +endif() + +mark_as_advanced (WAYLAND_LIBRARY WAYLAND_INCLUDE_DIR) diff --git a/project/cmake/treedata/optional/common/wayland.txt b/project/cmake/treedata/optional/common/wayland.txt new file mode 100644 index 0000000000000..61451dbdc858b --- /dev/null +++ b/project/cmake/treedata/optional/common/wayland.txt @@ -0,0 +1 @@ +xbmc/windowing/wayland windowing/wayland # WAYLAND diff --git a/xbmc/windowing/wayland/CMakeLists.txt b/xbmc/windowing/wayland/CMakeLists.txt new file mode 100644 index 0000000000000..c8526b8791f5d --- /dev/null +++ b/xbmc/windowing/wayland/CMakeLists.txt @@ -0,0 +1,55 @@ +set(SOURCES Callback.cpp + Compositor.cpp + Display.cpp + EGLNativeTypeWayland.cpp + EventLoop.cpp + InputFactory.cpp + Keyboard.cpp + KeyboardProcessor.cpp + OpenGLSurface.cpp + Output.cpp + Pointer.cpp + PointerProcessor.cpp + PollThread.cpp + Region.cpp + Registry.cpp + Seat.cpp + Shell.cpp + ShellSurface.cpp + Surface.cpp + Wayland12EventQueueStrategy.cpp + WinEventsWayland.cpp + XBMCConnection.cpp + XBMCSurface.cpp + ../../input/linux/XKBCommonKeymap.cpp + ) + +set(HEADERS Callback.h + Compositor.h + CursorManager.h + Display.h + EGLNativeTypeWayland.h + EventListener.h + EventLoop.h + EventQueueStrategy.h + InputFactory.h + Keyboard.h + KeyboardProcessor.h + OpenGLSurface.h + Output.h + Pointer.h + PointerProcessor.h + PollThread.h + Region.h + Registry.h + Seat.h + Shell.h + ShellSurface.h + Surface.h + TimeoutManager.h + Wayland12EventQueueStrategy.h + WinEventsWayland.h + XBMCConnection.h + XBMCSurface.h) + +core_add_library(windowing_WAYLAND) From 68801ac0d660254a9bfd2227627cfb9cc3d1743b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 49/59] windowing/wayland/Compositor: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/CMakeLists.txt | 1 - xbmc/windowing/wayland/Compositor.cpp | 52 --------------------------- xbmc/windowing/wayland/Compositor.h | 27 +++++++++----- 3 files changed, 19 insertions(+), 61 deletions(-) delete mode 100644 xbmc/windowing/wayland/Compositor.cpp diff --git a/xbmc/windowing/wayland/CMakeLists.txt b/xbmc/windowing/wayland/CMakeLists.txt index c8526b8791f5d..bff9ddf46c86f 100644 --- a/xbmc/windowing/wayland/CMakeLists.txt +++ b/xbmc/windowing/wayland/CMakeLists.txt @@ -1,5 +1,4 @@ set(SOURCES Callback.cpp - Compositor.cpp Display.cpp EGLNativeTypeWayland.cpp EventLoop.cpp diff --git a/xbmc/windowing/wayland/Compositor.cpp b/xbmc/windowing/wayland/Compositor.cpp deleted file mode 100644 index b71889194dff1..0000000000000 --- a/xbmc/windowing/wayland/Compositor.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2011-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include - -#include "Compositor.h" - -namespace xw = xbmc::wayland; - -xw::Compositor::Compositor(struct wl_compositor *compositor) : - m_compositor(compositor) -{ -} - -xw::Compositor::~Compositor() -{ - wl_compositor_destroy(m_compositor); -} - -struct wl_compositor * -xw::Compositor::GetWlCompositor() -{ - return m_compositor; -} - -struct wl_surface * -xw::Compositor::CreateSurface() const -{ - return wl_compositor_create_surface(m_compositor); -} - -struct wl_region * -xw::Compositor::CreateRegion() const -{ - return wl_compositor_create_region(m_compositor); -} diff --git a/xbmc/windowing/wayland/Compositor.h b/xbmc/windowing/wayland/Compositor.h index 0848743423b74..eb73ef41b8cb7 100644 --- a/xbmc/windowing/wayland/Compositor.h +++ b/xbmc/windowing/wayland/Compositor.h @@ -19,9 +19,8 @@ * . * */ -struct wl_compositor; -struct wl_surface; -struct wl_region; + +#include namespace xbmc { @@ -31,23 +30,35 @@ class Compositor { public: - explicit Compositor(struct wl_compositor *compositor); - ~Compositor(); + explicit Compositor(struct wl_compositor *compositor) : + m_compositor(compositor) + { + } + + ~Compositor() { + wl_compositor_destroy(m_compositor); + } Compositor(const Compositor &) = delete; Compositor &operator=(const Compositor &) = delete; - struct wl_compositor * GetWlCompositor(); + struct wl_compositor * GetWlCompositor() { + return m_compositor; + } /* Creates a "surface" on the compositor. This is not a renderable * surface immediately, a renderable "buffer" must be bound to it * (usually an EGL Window) */ - struct wl_surface * CreateSurface() const; + struct wl_surface * CreateSurface() const { + return wl_compositor_create_surface(m_compositor); + } /* Creates a "region" on the compositor side. Server side regions * are manipulated on the client side and then can be used to * affect rendering and input on the server side */ - struct wl_region * CreateRegion() const; + struct wl_region * CreateRegion() const { + return wl_compositor_create_region(m_compositor); + } private: From 4fb83d6e94d6b5219b2ae3a3485ba1aa177dc98b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 50/59] windowing/wayland/Keyboard: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/Keyboard.cpp | 6 ------ xbmc/windowing/wayland/Keyboard.h | 4 +++- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/xbmc/windowing/wayland/Keyboard.cpp b/xbmc/windowing/wayland/Keyboard.cpp index d86e412d955e4..51ba813c50855 100644 --- a/xbmc/windowing/wayland/Keyboard.cpp +++ b/xbmc/windowing/wayland/Keyboard.cpp @@ -23,7 +23,6 @@ #include "utils/ScopeExit.hxx" -#include #include #include "input/linux/XKBCommonKeymap.h" @@ -64,11 +63,6 @@ xw::Keyboard::Keyboard(struct wl_keyboard *keyboard, wl_keyboard_add_listener(m_keyboard, &m_listener, this); } -xw::Keyboard::~Keyboard() -{ - wl_keyboard_destroy(m_keyboard); -} - void xw::Keyboard::HandleKeymapCallback(void *data, struct wl_keyboard *keyboard, uint32_t format, diff --git a/xbmc/windowing/wayland/Keyboard.h b/xbmc/windowing/wayland/Keyboard.h index 7858ccbb746ac..cafb51256b86e 100644 --- a/xbmc/windowing/wayland/Keyboard.h +++ b/xbmc/windowing/wayland/Keyboard.h @@ -75,7 +75,9 @@ class Keyboard Keyboard(struct wl_keyboard *, IKeyboardReceiver &); - ~Keyboard(); + ~Keyboard() { + wl_keyboard_destroy(m_keyboard); + } Keyboard(const Keyboard &) = delete; Keyboard &operator=(const Keyboard &) = delete; From 268779343fa64e7b4cd30f9b0086eda42d3b5905 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 51/59] windowing/wayland/Output: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/Output.cpp | 45 ------------------------------- xbmc/windowing/wayland/Output.h | 32 +++++++++++++++++----- 2 files changed, 25 insertions(+), 52 deletions(-) diff --git a/xbmc/windowing/wayland/Output.cpp b/xbmc/windowing/wayland/Output.cpp index 5ad2f91ad42f0..bebaa8091005e 100644 --- a/xbmc/windowing/wayland/Output.cpp +++ b/xbmc/windowing/wayland/Output.cpp @@ -21,8 +21,6 @@ #include #include -#include - #include "Output.h" namespace xw = xbmc::wayland; @@ -45,17 +43,6 @@ xw::Output::Output(struct wl_output *output) : reinterpret_cast(this)); } -xw::Output::~Output() -{ - wl_output_destroy(m_output); -} - -struct wl_output * -xw::Output::GetWlOutput() -{ - return m_output; -} - /* It is a precondition violation to use CurrentMode() and * PreferredMode() before output modes have arrived yet, use * a synchronization function to ensure that this is the case */ @@ -79,24 +66,6 @@ xw::Output::PreferredMode() return m_preferred; } -const std::vector & -xw::Output::AllModes() -{ - return m_modes; -} - -const xw::Output::PhysicalGeometry & -xw::Output::Geometry() -{ - return m_geometry; -} - -uint32_t -xw::Output::ScaleFactor() -{ - return m_scaleFactor; -} - void xw::Output::GeometryCallback(void *data, struct wl_output *output, @@ -232,17 +201,3 @@ xw::Output::Mode(uint32_t flags, m_preferredValid = true; } } - -void -xw::Output::Done() -{ -} - -/* This function is called whenever the scaling factor for this - * output changes. It there for clients to support HiDPI displays, - * although unused as of present */ -void -xw::Output::Scale(int32_t factor) -{ - m_scaleFactor = factor; -} diff --git a/xbmc/windowing/wayland/Output.h b/xbmc/windowing/wayland/Output.h index 8653d6f3ed303..0e9645f853c3f 100644 --- a/xbmc/windowing/wayland/Output.h +++ b/xbmc/windowing/wayland/Output.h @@ -32,7 +32,9 @@ struct Output public: Output(struct wl_output *); - ~Output(); + ~Output() { + wl_output_destroy(m_output); + } Output(const Output &) = delete; Output &operator=(const Output &) = delete; @@ -54,7 +56,9 @@ struct Output enum wl_output_transform outputTransformation; }; - struct wl_output * GetWlOutput(); + struct wl_output * GetWlOutput() { + return m_output; + } /* It is a precondition violation to use the following four * functions when the first modes have not yet been received. @@ -74,10 +78,14 @@ struct Output * of this size in order to avoid scaling. */ const ModeGeometry & PreferredMode(); - const std::vector & AllModes(); + const std::vector & AllModes() const { + return m_modes; + } /* The geometry represents the physical geometry of this monitor */ - const PhysicalGeometry & Geometry(); + const PhysicalGeometry & Geometry() const { + return m_geometry; + } /* The scale factor of this output is an integer value representing * the number of output pixels per hardware pixel. For instance, @@ -86,7 +94,9 @@ struct Output * "2". This is useful for supporting HiDPI display modes where, * for instance we allocate a 3360x2100 buffer but display our UI * elements at 1680x1050 */ - uint32_t ScaleFactor(); + uint32_t ScaleFactor() const { + return m_scaleFactor; + } static void GeometryCallback(void *, struct wl_output *, @@ -126,8 +136,16 @@ struct Output int32_t width, int32_t height, int32_t refresh); - void Scale(int32_t); - void Done(); + + /* This function is called whenever the scaling factor for this + * output changes. It there for clients to support HiDPI displays, + * although unused as of present */ + void Scale(int32_t factor) { + m_scaleFactor = factor; + } + + void Done() { + } struct wl_output *m_output; From 345b849124caf26333094f8883a4204a67ace333 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:08 +0200 Subject: [PATCH 52/59] windowing/wayland/Pointer: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/Pointer.cpp | 15 --------------- xbmc/windowing/wayland/Pointer.h | 8 ++++++-- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/xbmc/windowing/wayland/Pointer.cpp b/xbmc/windowing/wayland/Pointer.cpp index 9a4082c431f1d..d1b53cb8bf8af 100644 --- a/xbmc/windowing/wayland/Pointer.cpp +++ b/xbmc/windowing/wayland/Pointer.cpp @@ -21,8 +21,6 @@ #include #include -#include - #include "Pointer.h" namespace xw = xbmc::wayland; @@ -44,19 +42,6 @@ xw::Pointer::Pointer(struct wl_pointer *pointer, wl_pointer_add_listener(pointer, &m_listener, this); } -xw::Pointer::~Pointer() -{ - wl_pointer_destroy(m_pointer); -} - -void xw::Pointer::SetCursor(uint32_t serial, - struct wl_surface *surface, - int32_t hotspot_x, - int32_t hotspot_y) -{ - wl_pointer_set_cursor(m_pointer, serial, surface, hotspot_x, hotspot_y); -} - void xw::Pointer::HandleEnterCallback(void *data, struct wl_pointer *pointer, uint32_t serial, diff --git a/xbmc/windowing/wayland/Pointer.h b/xbmc/windowing/wayland/Pointer.h index 0309f9b5bd62e..e1e50b5024711 100644 --- a/xbmc/windowing/wayland/Pointer.h +++ b/xbmc/windowing/wayland/Pointer.h @@ -57,7 +57,9 @@ class Pointer Pointer(struct wl_pointer *, IPointerReceiver &); - ~Pointer(); + ~Pointer() { + wl_pointer_destroy(m_pointer); + } struct wl_pointer * GetWlPointer(); @@ -67,7 +69,9 @@ class Pointer void SetCursor(uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, - int32_t hotspot_y); + int32_t hotspot_y) { + wl_pointer_set_cursor(m_pointer, serial, surface, hotspot_x, hotspot_y); + } static void HandleEnterCallback(void *, struct wl_pointer *, From 61b0be5f5cc18b18efa8477766ff609d821cce01 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:09 +0200 Subject: [PATCH 53/59] windowing/wayland/Region: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/CMakeLists.txt | 1 - xbmc/windowing/wayland/Region.cpp | 49 --------------------------- xbmc/windowing/wayland/Region.h | 20 ++++++++--- 3 files changed, 15 insertions(+), 55 deletions(-) delete mode 100644 xbmc/windowing/wayland/Region.cpp diff --git a/xbmc/windowing/wayland/CMakeLists.txt b/xbmc/windowing/wayland/CMakeLists.txt index bff9ddf46c86f..21b059c2a2fa4 100644 --- a/xbmc/windowing/wayland/CMakeLists.txt +++ b/xbmc/windowing/wayland/CMakeLists.txt @@ -10,7 +10,6 @@ set(SOURCES Callback.cpp Pointer.cpp PointerProcessor.cpp PollThread.cpp - Region.cpp Registry.cpp Seat.cpp Shell.cpp diff --git a/xbmc/windowing/wayland/Region.cpp b/xbmc/windowing/wayland/Region.cpp deleted file mode 100644 index 34cfe32b957de..0000000000000 --- a/xbmc/windowing/wayland/Region.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2011-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include - -#include "Region.h" - -namespace xw = xbmc::wayland; - -xw::Region::Region(struct wl_region *region) : - m_region(region) -{ -} - -xw::Region::~Region() -{ - wl_region_destroy(m_region); -} - -struct wl_region * -xw::Region::GetWlRegion() -{ - return m_region; -} - -void -xw::Region::AddRectangle(int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - wl_region_add(m_region, x, y, width, height); -} diff --git a/xbmc/windowing/wayland/Region.h b/xbmc/windowing/wayland/Region.h index 3029962e2d67a..4093a38ce38b8 100644 --- a/xbmc/windowing/wayland/Region.h +++ b/xbmc/windowing/wayland/Region.h @@ -20,7 +20,7 @@ * */ -struct wl_region; +#include namespace xbmc { @@ -30,18 +30,28 @@ class Region { public: - explicit Region(struct wl_region *); - ~Region(); + explicit Region(struct wl_region *region) : + m_region(region) + { + } + + ~Region() { + wl_region_destroy(m_region); + } Region(const Region &) = delete; Region &operator=(const Region &) = delete; - struct wl_region * GetWlRegion(); + struct wl_region * GetWlRegion() { + return m_region; + } void AddRectangle(int32_t x, int32_t y, int32_t width, - int32_t height); + int32_t height) { + wl_region_add(m_region, x, y, width, height); + } private: From cd23fe82bfc334dfeff4644546276d776f123f6c Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:09 +0200 Subject: [PATCH 54/59] windowing/wayland/Registry: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/Registry.cpp | 25 ------------------------- xbmc/windowing/wayland/Registry.h | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/xbmc/windowing/wayland/Registry.cpp b/xbmc/windowing/wayland/Registry.cpp index ead9e1ffcb777..c9caa2ac265cc 100644 --- a/xbmc/windowing/wayland/Registry.cpp +++ b/xbmc/windowing/wayland/Registry.cpp @@ -17,7 +17,6 @@ * . * */ -#include #include "Registry.h" @@ -29,13 +28,6 @@ const struct wl_registry_listener xw::Registry::m_listener = Registry::HandleRemoveGlobalCallback }; -/* Only one observer may be registered at a time */ -void -xw::ExtraWaylandGlobals::SetHandler(const GlobalHandler &handler) -{ - m_handler = handler; -} - void xw::ExtraWaylandGlobals::NewGlobal(struct wl_registry *registry, uint32_t name, @@ -77,23 +69,6 @@ xw::Registry::Registry(struct wl_display *display, reinterpret_cast(this)); } -xw::Registry::~Registry() -{ - wl_registry_destroy(m_registry); -} - -/* Once a global becomes available, we immediately bind to it here - * and then notify the injected listener interface that the global - * is available on a named object. This allows that interface to - * respond to the arrival of the new global how it wishes */ -void * -xw::Registry::BindInternal(uint32_t name, - const struct wl_interface *interface, - uint32_t version) -{ - return wl_registry_bind(m_registry, name, interface, version); -} - void xw::Registry::HandleGlobal(uint32_t name, const char *interface, diff --git a/xbmc/windowing/wayland/Registry.h b/xbmc/windowing/wayland/Registry.h index 30abe3f656131..a2482b8117430 100644 --- a/xbmc/windowing/wayland/Registry.h +++ b/xbmc/windowing/wayland/Registry.h @@ -41,7 +41,10 @@ class ExtraWaylandGlobals const char *, uint32_t)> GlobalHandler; - void SetHandler(const GlobalHandler &); + void SetHandler(const GlobalHandler &handler) { + m_handler = handler; + } + void NewGlobal(struct wl_registry *, uint32_t, const char *, @@ -72,7 +75,9 @@ class Registry Registry(struct wl_display *display, IWaylandRegistration ®istration); - ~Registry(); + ~Registry() { + wl_registry_destroy(m_registry); + } Registry(const Registry &) = delete; Registry &operator=(const Registry &) = delete; @@ -99,9 +104,15 @@ class Registry static void HandleRemoveGlobalCallback(void *, struct wl_registry *, uint32_t name); + /* Once a global becomes available, we immediately bind to it here + * and then notify the injected listener interface that the global + * is available on a named object. This allows that interface to + * respond to the arrival of the new global how it wishes */ void *BindInternal(uint32_t name, const struct wl_interface *interface, - uint32_t version); + uint32_t version) { + return wl_registry_bind(m_registry, name, interface, version); + } struct wl_registry *m_registry; IWaylandRegistration &m_registration; From d805a6251f4b793f74b645095c5378ba2f38b353 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:09 +0200 Subject: [PATCH 55/59] windowing/wayland/Seat: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/Seat.cpp | 7 ------- xbmc/windowing/wayland/Seat.h | 4 +++- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/xbmc/windowing/wayland/Seat.cpp b/xbmc/windowing/wayland/Seat.cpp index 69baa094e2490..c38de028684c0 100644 --- a/xbmc/windowing/wayland/Seat.cpp +++ b/xbmc/windowing/wayland/Seat.cpp @@ -21,8 +21,6 @@ #include #include -#include - #include "Seat.h" namespace xw = xbmc::wayland; @@ -43,11 +41,6 @@ xw::Seat::Seat(struct wl_seat *seat, wl_seat_add_listener(m_seat, &m_listener, reinterpret_cast(this)); } -xw::Seat::~Seat() -{ - wl_seat_destroy(m_seat); -} - void xw::Seat::HandleCapabilitiesCallback(void *data, struct wl_seat *seat, uint32_t cap) diff --git a/xbmc/windowing/wayland/Seat.h b/xbmc/windowing/wayland/Seat.h index 07e30606a6be6..45c367b78f5d5 100644 --- a/xbmc/windowing/wayland/Seat.h +++ b/xbmc/windowing/wayland/Seat.h @@ -44,7 +44,9 @@ class Seat Seat(struct wl_seat *, IInputReceiver &); - ~Seat(); + ~Seat() { + wl_seat_destroy(m_seat); + } Seat(const Seat &) = delete; Seat &operator=(const Seat &) = delete; From 0b58d0ddb44a70543cf5a9066bf4cfdfa9145cf2 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:09 +0200 Subject: [PATCH 56/59] windowing/wayland/Shell: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/CMakeLists.txt | 1 - xbmc/windowing/wayland/Shell.cpp | 46 --------------------------- xbmc/windowing/wayland/Shell.h | 23 ++++++++++---- 3 files changed, 16 insertions(+), 54 deletions(-) delete mode 100644 xbmc/windowing/wayland/Shell.cpp diff --git a/xbmc/windowing/wayland/CMakeLists.txt b/xbmc/windowing/wayland/CMakeLists.txt index 21b059c2a2fa4..73a880333d818 100644 --- a/xbmc/windowing/wayland/CMakeLists.txt +++ b/xbmc/windowing/wayland/CMakeLists.txt @@ -12,7 +12,6 @@ set(SOURCES Callback.cpp PollThread.cpp Registry.cpp Seat.cpp - Shell.cpp ShellSurface.cpp Surface.cpp Wayland12EventQueueStrategy.cpp diff --git a/xbmc/windowing/wayland/Shell.cpp b/xbmc/windowing/wayland/Shell.cpp deleted file mode 100644 index f804c0b80c502..0000000000000 --- a/xbmc/windowing/wayland/Shell.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011-2013 Team XBMC - * http://xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ -#include - -#include "Shell.h" - -namespace xw = xbmc::wayland; - -xw::Shell::Shell(struct wl_shell *shell) : - m_shell(shell) -{ -} - -xw::Shell::~Shell() -{ - wl_shell_destroy(m_shell); -} - -struct wl_shell * -xw::Shell::GetWlShell() -{ - return m_shell; -} - -struct wl_shell_surface * -xw::Shell::CreateShellSurface(struct wl_surface *surface) -{ - return wl_shell_get_shell_surface(m_shell, surface); -} diff --git a/xbmc/windowing/wayland/Shell.h b/xbmc/windowing/wayland/Shell.h index b901268a81ee2..5bd5b4f437335 100644 --- a/xbmc/windowing/wayland/Shell.h +++ b/xbmc/windowing/wayland/Shell.h @@ -20,9 +20,7 @@ * */ -struct wl_shell; -struct wl_shell_surface; -struct wl_surface; +#include namespace xbmc { @@ -32,14 +30,25 @@ class Shell { public: - explicit Shell(struct wl_shell *shell); - ~Shell(); + explicit Shell(struct wl_shell *shell) : + m_shell(shell) + { + } + + ~Shell() { + wl_shell_destroy(m_shell); + } Shell(const Shell &) = delete; Shell &operator=(const Shell &) = delete; - struct wl_shell * GetWlShell(); - struct wl_shell_surface * CreateShellSurface(struct wl_surface *); + struct wl_shell * GetWlShell() { + return m_shell; + } + + struct wl_shell_surface * CreateShellSurface(struct wl_surface *surface) { + return wl_shell_get_shell_surface(m_shell, surface); + } private: From 5e57f61e38bd182b484f12f9b1ab66ed51d42eac Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:09 +0200 Subject: [PATCH 57/59] windowing/wayland/ShellSurface: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/ShellSurface.cpp | 22 ---------------------- xbmc/windowing/wayland/ShellSurface.h | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/xbmc/windowing/wayland/ShellSurface.cpp b/xbmc/windowing/wayland/ShellSurface.cpp index 6713acf056d6a..5d70ce2ba4950 100644 --- a/xbmc/windowing/wayland/ShellSurface.cpp +++ b/xbmc/windowing/wayland/ShellSurface.cpp @@ -37,28 +37,6 @@ xw::ShellSurface::ShellSurface(struct wl_shell_surface *shell_surface) : reinterpret_cast(this)); } -xw::ShellSurface::~ShellSurface() -{ - wl_shell_surface_destroy(m_shellSurface); -} - -struct wl_shell_surface * -xw::ShellSurface::GetWlShellSurface() -{ - return m_shellSurface; -} - -void -xw::ShellSurface::SetFullscreen(enum wl_shell_surface_fullscreen_method method, - uint32_t framerate, - struct wl_output *output) -{ - wl_shell_surface_set_fullscreen(m_shellSurface, - method, - framerate, - output); -} - void xw::ShellSurface::HandlePingCallback(void *data, struct wl_shell_surface *shell_surface, diff --git a/xbmc/windowing/wayland/ShellSurface.h b/xbmc/windowing/wayland/ShellSurface.h index 0ee1c14518239..9c88f040f30a0 100644 --- a/xbmc/windowing/wayland/ShellSurface.h +++ b/xbmc/windowing/wayland/ShellSurface.h @@ -30,15 +30,25 @@ class ShellSurface public: explicit ShellSurface(struct wl_shell_surface *shellSurface); - ~ShellSurface(); + ~ShellSurface() { + wl_shell_surface_destroy(m_shellSurface); + } ShellSurface(const ShellSurface &) = delete; ShellSurface &operator=(const ShellSurface &) = delete; - struct wl_shell_surface * GetWlShellSurface(); + struct wl_shell_surface * GetWlShellSurface() { + return m_shellSurface; + } + void SetFullscreen(enum wl_shell_surface_fullscreen_method method, uint32_t framerate, - struct wl_output *output); + struct wl_output *output) { + wl_shell_surface_set_fullscreen(m_shellSurface, + method, + framerate, + output); + } static const wl_shell_surface_listener m_listener; From 001cc9bdf4fa6aa98f394097bdf01131d04982d7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Apr 2017 14:38:09 +0200 Subject: [PATCH 58/59] windowing/wayland/Surface: inline trivial methods Signed-off-by: memeka --- xbmc/windowing/wayland/Surface.cpp | 36 ------------------------------ xbmc/windowing/wayland/Surface.h | 32 ++++++++++++++++++-------- 2 files changed, 23 insertions(+), 45 deletions(-) diff --git a/xbmc/windowing/wayland/Surface.cpp b/xbmc/windowing/wayland/Surface.cpp index a5db51f78ed8b..59a6b8c0970d6 100644 --- a/xbmc/windowing/wayland/Surface.cpp +++ b/xbmc/windowing/wayland/Surface.cpp @@ -17,7 +17,6 @@ * . * */ -#include #include "Surface.h" @@ -34,12 +33,6 @@ xw::WaylandSurfaceListener::GetInstance() return *m_instance; } -void -xw::WaylandSurfaceListener::SetHandler(const Handler &handler) -{ - m_handler = handler; -} - void xw::WaylandSurfaceListener::SurfaceCreated(xw::Surface &surface) { @@ -52,32 +45,3 @@ xw::Surface::Surface(struct wl_surface *surface) : { WaylandSurfaceListener::GetInstance().SurfaceCreated(*this); } - -xw::Surface::~Surface() -{ - wl_surface_destroy(m_surface); -} - -struct wl_surface * -xw::Surface::GetWlSurface() -{ - return m_surface; -} - -struct wl_callback * -xw::Surface::CreateFrameCallback() -{ - return wl_surface_frame(m_surface); -} - -void -xw::Surface::SetOpaqueRegion(struct wl_region *region) -{ - wl_surface_set_opaque_region(m_surface, region); -} - -void -xw::Surface::Commit() -{ - wl_surface_commit(m_surface); -} diff --git a/xbmc/windowing/wayland/Surface.h b/xbmc/windowing/wayland/Surface.h index 195bb973c80e0..2918ceba262bb 100644 --- a/xbmc/windowing/wayland/Surface.h +++ b/xbmc/windowing/wayland/Surface.h @@ -22,9 +22,7 @@ #include #include -struct wl_surface; -struct wl_callback; -struct wl_region; +#include namespace xbmc { @@ -35,15 +33,28 @@ class Surface public: explicit Surface(struct wl_surface *surface); - ~Surface(); + ~Surface() { + wl_surface_destroy(m_surface); + } Surface(const Surface &) = delete; Surface &operator=(const Surface &) = delete; - struct wl_surface * GetWlSurface(); - struct wl_callback * CreateFrameCallback(); - void SetOpaqueRegion(struct wl_region *region); - void Commit(); + struct wl_surface * GetWlSurface() { + return m_surface; + } + + struct wl_callback * CreateFrameCallback() { + return wl_surface_frame(m_surface); + } + + void SetOpaqueRegion(struct wl_region *region) { + wl_surface_set_opaque_region(m_surface, region); + } + + void Commit() { + wl_surface_commit(m_surface); + } private: @@ -61,7 +72,10 @@ class WaylandSurfaceListener typedef std::function Handler; - void SetHandler(const Handler &); + void SetHandler(const Handler &handler) { + m_handler = handler; + } + void SurfaceCreated(Surface &); static WaylandSurfaceListener & GetInstance(); From d3d3b5a17e2215302c9dc17f24e0a67bfc366f80 Mon Sep 17 00:00:00 2001 From: memeka Date: Tue, 10 Oct 2017 20:42:28 +1030 Subject: [PATCH 59/59] replace memcpy with NEON-optimized fast_memcpy function --- .../VideoPlayer/DVDCodecs/DVDCodecUtils.cpp | 33 +- .../DVDCodecs/Video/DVDVideoCodecMFC.cpp | 5 +- .../VideoRenderers/LinuxRendererGLES.cpp | 1 + .../VideoRenderers/RenderCapture.cpp | 7 +- xbmc/utils/CMakeLists.txt | 2 + xbmc/utils/Makefile.in | 2 + xbmc/utils/fastmemcpy-arm.S | 528 ++++++++++++++++++ xbmc/utils/fastmemcpy.c | 396 +++++++++++++ xbmc/utils/fastmemcpy.h | 35 ++ 9 files changed, 988 insertions(+), 21 deletions(-) create mode 100644 xbmc/utils/fastmemcpy-arm.S create mode 100644 xbmc/utils/fastmemcpy.c create mode 100644 xbmc/utils/fastmemcpy.h diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.cpp index ac4e063460a39..07b6603c1cab7 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.cpp @@ -22,6 +22,7 @@ #include "DVDClock.h" #include "cores/VideoPlayer/VideoRenderers/RenderManager.h" #include "utils/log.h" +#include "utils/fastmemcpy.h" #include "cores/FFmpeg.h" #include "Util.h" @@ -91,7 +92,7 @@ bool CDVDCodecUtils::CopyPicture(DVDVideoPicture* pDst, DVDVideoPicture* pSrc) for (int y = 0; y < h; y++) { - memcpy(d, s, w); + fast_memcpy(d, s, w); s += pSrc->iLineSize[0]; d += pDst->iLineSize[0]; } @@ -103,7 +104,7 @@ bool CDVDCodecUtils::CopyPicture(DVDVideoPicture* pDst, DVDVideoPicture* pSrc) d = pDst->data[1]; for (int y = 0; y < h; y++) { - memcpy(d, s, w); + fast_memcpy(d, s, w); s += pSrc->iLineSize[1]; d += pDst->iLineSize[1]; } @@ -112,7 +113,7 @@ bool CDVDCodecUtils::CopyPicture(DVDVideoPicture* pDst, DVDVideoPicture* pSrc) d = pDst->data[2]; for (int y = 0; y < h; y++) { - memcpy(d, s, w); + fast_memcpy(d, s, w); s += pSrc->iLineSize[2]; d += pDst->iLineSize[2]; } @@ -127,13 +128,13 @@ bool CDVDCodecUtils::CopyPicture(YV12Image* pImage, DVDVideoPicture *pSrc) int h = pImage->height; if ((w == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0])) { - memcpy(d, s, w*h); + fast_memcpy(d, s, w*h); } else { for (int y = 0; y < h; y++) { - memcpy(d, s, w); + fast_memcpy(d, s, w); s += pSrc->iLineSize[0]; d += pImage->stride[0]; } @@ -144,13 +145,13 @@ bool CDVDCodecUtils::CopyPicture(YV12Image* pImage, DVDVideoPicture *pSrc) h =(pImage->height >> pImage->cshift_y); if ((w==pSrc->iLineSize[1]) && ((unsigned int) pSrc->iLineSize[1]==pImage->stride[1])) { - memcpy(d, s, w*h); + fast_memcpy(d, s, w*h); } else { for (int y = 0; y < h; y++) { - memcpy(d, s, w); + fast_memcpy(d, s, w); s += pSrc->iLineSize[1]; d += pImage->stride[1]; } @@ -159,13 +160,13 @@ bool CDVDCodecUtils::CopyPicture(YV12Image* pImage, DVDVideoPicture *pSrc) d = pImage->plane[2]; if ((w==pSrc->iLineSize[2]) && ((unsigned int) pSrc->iLineSize[2]==pImage->stride[2])) { - memcpy(d, s, w*h); + fast_memcpy(d, s, w*h); } else { for (int y = 0; y < h; y++) { - memcpy(d, s, w); + fast_memcpy(d, s, w); s += pSrc->iLineSize[2]; d += pImage->stride[2]; } @@ -203,7 +204,7 @@ DVDVideoPicture* CDVDCodecUtils::ConvertToNV12Picture(DVDVideoPicture *pSrc) uint8_t *d = pPicture->data[0]; for (int y = 0; y < (int)pSrc->iHeight; y++) { - memcpy(d, s, pSrc->iWidth); + fast_memcpy(d, s, pSrc->iWidth); s += pSrc->iLineSize[0]; d += pPicture->iLineSize[0]; } @@ -294,13 +295,13 @@ bool CDVDCodecUtils::CopyNV12Picture(YV12Image* pImage, DVDVideoPicture *pSrc) // Copy Y if ((w == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0])) { - memcpy(d, s, w*h); + fast_memcpy(d, s, w*h); } else { for (int y = 0; y < h; y++) { - memcpy(d, s, w); + fast_memcpy(d, s, w); s += pSrc->iLineSize[0]; d += pImage->stride[0]; } @@ -313,13 +314,13 @@ bool CDVDCodecUtils::CopyNV12Picture(YV12Image* pImage, DVDVideoPicture *pSrc) // Copy packed UV (width is same as for Y as it's both U and V components) if ((w==pSrc->iLineSize[1]) && ((unsigned int) pSrc->iLineSize[1]==pImage->stride[1])) { - memcpy(d, s, w*h); + fast_memcpy(d, s, w*h); } else { for (int y = 0; y < h; y++) { - memcpy(d, s, w); + fast_memcpy(d, s, w); s += pSrc->iLineSize[1]; d += pImage->stride[1]; } @@ -338,13 +339,13 @@ bool CDVDCodecUtils::CopyYUV422PackedPicture(YV12Image* pImage, DVDVideoPicture // Copy YUYV if ((w * 2 == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0])) { - memcpy(d, s, w*h*2); + fast_memcpy(d, s, w*h*2); } else { for (int y = 0; y < h; y++) { - memcpy(d, s, w*2); + fast_memcpy(d, s, w*2); s += pSrc->iLineSize[0]; d += pImage->stride[0]; } diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.cpp index 2496ee69af840..1f741ab98c8b6 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecMFC.cpp @@ -17,6 +17,7 @@ #endif #include "DVDVideoCodecMFC.h" +#include "utils/fastmemcpy.h" #include #include @@ -304,7 +305,7 @@ bool CDVDVideoCodecMFC::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { return false; // Fill it with the header sinkBuffer.iBytesUsed[0] = extraSize; - memcpy(sinkBuffer.cPlane[0], extraData, extraSize); + fast_memcpy(sinkBuffer.cPlane[0], extraData, extraSize); // Enqueue buffer if (!m_MFCOutput->PushBuffer(&sinkBuffer)) return false; @@ -484,7 +485,7 @@ int CDVDVideoCodecMFC::Decode(BYTE* pData, int iSize, double dts, double pts) { if (m_MFCOutput->GetBuffer(m_Buffer)) { debug_log(LOGDEBUG, "%s::%s - Got empty buffer %d from MFC Output, filling", CLASSNAME, __func__, m_Buffer->iIndex); m_Buffer->iBytesUsed[0] = demuxer_bytes; - memcpy((uint8_t *)m_Buffer->cPlane[0], demuxer_content, m_Buffer->iBytesUsed[0]); + fast_memcpy((uint8_t *)m_Buffer->cPlane[0], demuxer_content, m_Buffer->iBytesUsed[0]); long* longPts = (long*)&pts; m_Buffer->timeStamp.tv_sec = longPts[0]; m_Buffer->timeStamp.tv_usec = longPts[1]; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp index e9bdfba9ec65e..7024bcc91877d 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp @@ -31,6 +31,7 @@ #include #include "guilib/MatrixGLES.h" #include "LinuxRendererGLES.h" +#include "utils/fastmemcpy.h" #include "utils/MathUtils.h" #include "utils/GLUtils.h" #include "utils/log.h" diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp index 9bf031095f765..34324808ff842 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp @@ -21,6 +21,7 @@ #include "RenderCapture.h" #include "utils/log.h" #include "windowing/WindowingFactory.h" +#include "utils/fastmemcpy.h" #include "settings/AdvancedSettings.h" #include "cores/IPlayer.h" extern "C" { @@ -297,7 +298,7 @@ void CRenderCaptureGL::PboToBuffer() if (pboPtr) { - memcpy(m_pixels, pboPtr, m_bufferSize); + fast_memcpy(m_pixels, pboPtr, m_bufferSize); SetState(CAPTURESTATE_DONE); } else @@ -484,12 +485,12 @@ void CRenderCaptureDX::SurfaceToBuffer() //if pitch is same, do a direct copy, otherwise copy one line at a time if (lockedRect.RowPitch == m_width * 4) { - memcpy(m_pixels, lockedRect.pData, m_width * m_height * 4); + fast_memcpy(m_pixels, lockedRect.pData, m_width * m_height * 4); } else { for (unsigned int y = 0; y < m_height; y++) - memcpy(m_pixels + y * m_width * 4, (uint8_t*)lockedRect.pData + y * lockedRect.RowPitch, m_width * 4); + fast_memcpy(m_pixels + y * m_width * 4, (uint8_t*)lockedRect.pData + y * lockedRect.RowPitch, m_width * 4); } pContext->Unmap(m_copySurface, 0); SetState(CAPTURESTATE_DONE); diff --git a/xbmc/utils/CMakeLists.txt b/xbmc/utils/CMakeLists.txt index 2c1d4096bd077..354fef0373ab5 100644 --- a/xbmc/utils/CMakeLists.txt +++ b/xbmc/utils/CMakeLists.txt @@ -15,6 +15,8 @@ set(SOURCES ActorProtocol.cpp EndianSwap.cpp Environment.cpp Fanart.cpp + fastmemcpy.c + fastmemcpy-arm.S FileOperationJob.cpp FileUtils.cpp fstrcmp.c diff --git a/xbmc/utils/Makefile.in b/xbmc/utils/Makefile.in index 7ec1b21f1d870..dac33a9e24340 100644 --- a/xbmc/utils/Makefile.in +++ b/xbmc/utils/Makefile.in @@ -15,6 +15,8 @@ SRCS += DatabaseUtils.cpp SRCS += EndianSwap.cpp SRCS += Environment.cpp SRCS += Fanart.cpp +SRCS += fastmemcpy.c +SRCS += fastmemcpy-arm.S SRCS += FileOperationJob.cpp SRCS += FileUtils.cpp SRCS += fstrcmp.c diff --git a/xbmc/utils/fastmemcpy-arm.S b/xbmc/utils/fastmemcpy-arm.S new file mode 100644 index 0000000000000..6cb8b0cfc6cba --- /dev/null +++ b/xbmc/utils/fastmemcpy-arm.S @@ -0,0 +1,528 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#if defined(__arm__) && !defined(TARGET_ANDROID) && !defined(TARGET_DARWIN_IOS) +#if defined(__ARM_NEON__) + + .text +#ifndef __APPLE__ + .fpu neon + .global fast_memcpy + .type fast_memcpy, %function +#else + .globl _fast_memcpy +#endif + .align 4 + +/* a prefetch distance of 4 cache-lines works best experimentally */ +#define CACHE_LINE_SIZE 64 +#define PREFETCH_DISTANCE (CACHE_LINE_SIZE*4) + +#ifndef __APPLE__ + .fnstart + .save {r0, lr} +fast_memcpy: +#else +_fast_memcpy: +#endif + stmfd sp!, {r0, lr} + + /* start preloading as early as possible */ + pld [r1, #(CACHE_LINE_SIZE*0)] + pld [r1, #(CACHE_LINE_SIZE*1)] + + /* do we have at least 16-bytes to copy (needed for alignment below) */ + cmp r2, #16 + blo 5f + + /* align destination to half cache-line for the write-buffer */ + rsb r3, r0, #0 + ands r3, r3, #0xF + beq 0f + + /* copy up to 15-bytes (count in r3) */ + sub r2, r2, r3 + movs ip, r3, lsl #31 + ldrmib lr, [r1], #1 + strmib lr, [r0], #1 + ldrcsb ip, [r1], #1 + ldrcsb lr, [r1], #1 + strcsb ip, [r0], #1 + strcsb lr, [r0], #1 + movs ip, r3, lsl #29 + bge 1f + // copies 4 bytes, destination 32-bits aligned + vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]! + vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]! +1: bcc 2f + // copies 8 bytes, destination 64-bits aligned + vld1.8 {d0}, [r1]! + vst1.8 {d0}, [r0, :64]! +2: + +0: /* preload immediately the next cache line, which we may need */ + pld [r1, #(CACHE_LINE_SIZE*0)] + pld [r1, #(CACHE_LINE_SIZE*1)] + + /* make sure we have at least 64 bytes to copy */ + subs r2, r2, #64 + blo 2f + + /* preload all the cache lines we need. + * NOTE: the number of pld below depends on PREFETCH_DISTANCE, + * ideally would would increase the distance in the main loop to + * avoid the goofy code below. In practice this doesn't seem to make + * a big difference. + */ + pld [r1, #(CACHE_LINE_SIZE*2)] + pld [r1, #(CACHE_LINE_SIZE*3)] + pld [r1, #(PREFETCH_DISTANCE)] + +1: /* The main loop copies 64 bytes at a time */ + vld1.8 {d0 - d3}, [r1]! + vld1.8 {d4 - d7}, [r1]! + pld [r1, #(PREFETCH_DISTANCE)] + subs r2, r2, #64 + vst1.8 {d0 - d3}, [r0, :128]! + vst1.8 {d4 - d7}, [r0, :128]! + bhs 1b + +2: /* fix-up the remaining count and make sure we have >= 32 bytes left */ + add r2, r2, #64 + subs r2, r2, #32 + blo 4f + +3: /* 32 bytes at a time. These cache lines were already preloaded */ + vld1.8 {d0 - d3}, [r1]! + subs r2, r2, #32 + vst1.8 {d0 - d3}, [r0, :128]! + bhs 3b + +4: /* less than 32 left */ + add r2, r2, #32 + tst r2, #0x10 + beq 5f + // copies 16 bytes, 128-bits aligned + vld1.8 {d0, d1}, [r1]! + vst1.8 {d0, d1}, [r0, :128]! + +5: /* copy up to 15-bytes (count in r2) */ + movs ip, r2, lsl #29 + bcc 1f + vld1.8 {d0}, [r1]! + vst1.8 {d0}, [r0]! +1: bge 2f + vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]! + vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]! +2: movs ip, r2, lsl #31 + ldrmib r3, [r1], #1 + ldrcsb ip, [r1], #1 + ldrcsb lr, [r1], #1 + strmib r3, [r0], #1 + strcsb ip, [r0], #1 + strcsb lr, [r0], #1 + + ldmfd sp!, {r0, lr} + bx lr +#ifndef __APPLE__ + .fnend +#endif + +#else /* __ARM_ARCH__ < 7 */ + + + .text + +#ifndef __APPLE__ + .global fast_memcpy + .type fast_memcpy, %function +#else + .globl _fast_memcpy +#endif + .align 4 + + /* + * Optimized memcpy() for ARM. + * + * note that memcpy() always returns the destination pointer, + * so we have to preserve R0. + */ + +#ifndef __APPLE__ +fast_memcpy: +#else +_fast_memcpy: +#endif + /* The stack must always be 64-bits aligned to be compliant with the + * ARM ABI. Since we have to save R0, we might as well save R4 + * which we can use for better pipelining of the reads below + */ +#ifndef __APPLE__ + .fnstart + .save {r0, r4, lr} +#endif + stmfd sp!, {r0, r4, lr} + /* Making room for r5-r11 which will be spilled later */ + .pad #28 + sub sp, sp, #28 + + // preload the destination because we'll align it to a cache line + // with small writes. Also start the source "pump". + //PLD (r0, #0) + //PLD (r1, #0) + //PLD (r1, #32) + + /* it simplifies things to take care of len<4 early */ + cmp r2, #4 + blo copy_last_3_and_return + + /* compute the offset to align the source + * offset = (4-(src&3))&3 = -src & 3 + */ + rsb r3, r1, #0 + ands r3, r3, #3 + beq src_aligned + + /* align source to 32 bits. We need to insert 2 instructions between + * a ldr[b|h] and str[b|h] because byte and half-word instructions + * stall 2 cycles. + */ + movs r12, r3, lsl #31 + sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */ + ldrmib r3, [r1], #1 + ldrcsb r4, [r1], #1 + ldrcsb r12,[r1], #1 + strmib r3, [r0], #1 + strcsb r4, [r0], #1 + strcsb r12,[r0], #1 + +src_aligned: + + /* see if src and dst are aligned together (congruent) */ + eor r12, r0, r1 + tst r12, #3 + bne non_congruent + + /* Use post-incriment mode for stm to spill r5-r11 to reserved stack + * frame. Don't update sp. + */ + stmea sp, {r5-r11} + + /* align the destination to a cache-line */ + rsb r3, r0, #0 + ands r3, r3, #0x1C + beq congruent_aligned32 + cmp r3, r2 + andhi r3, r2, #0x1C + + /* conditionnaly copies 0 to 7 words (length in r3) */ + movs r12, r3, lsl #28 + ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */ + ldmmiia r1!, {r8, r9} /* 8 bytes */ + stmcsia r0!, {r4, r5, r6, r7} + stmmiia r0!, {r8, r9} + tst r3, #0x4 + ldrne r10,[r1], #4 /* 4 bytes */ + strne r10,[r0], #4 + sub r2, r2, r3 + +congruent_aligned32: + /* + * here source is aligned to 32 bytes. + */ + +cached_aligned32: + subs r2, r2, #32 + blo less_than_32_left + + /* + * We preload a cache-line up to 64 bytes ahead. On the 926, this will + * stall only until the requested world is fetched, but the linefill + * continues in the the background. + * While the linefill is going, we write our previous cache-line + * into the write-buffer (which should have some free space). + * When the linefill is done, the writebuffer will + * start dumping its content into memory + * + * While all this is going, we then load a full cache line into + * 8 registers, this cache line should be in the cache by now + * (or partly in the cache). + * + * This code should work well regardless of the source/dest alignment. + * + */ + + // Align the preload register to a cache-line because the cpu does + // "critical word first" (the first word requested is loaded first). + bic r12, r1, #0x1F + add r12, r12, #64 + +1: ldmia r1!, { r4-r11 } + //PLD (r12, #64) + subs r2, r2, #32 + + // NOTE: if r12 is more than 64 ahead of r1, the following ldrhi + // for ARM9 preload will not be safely guarded by the preceding subs. + // When it is safely guarded the only possibility to have SIGSEGV here + // is because the caller overstates the length. + ldrhi r3, [r12], #32 /* cheap ARM9 preload */ + stmia r0!, { r4-r11 } + bhs 1b + + add r2, r2, #32 + + + + +less_than_32_left: + /* + * less than 32 bytes left at this point (length in r2) + */ + + /* skip all this if there is nothing to do, which should + * be a common case (if not executed the code below takes + * about 16 cycles) + */ + tst r2, #0x1F + beq 1f + + /* conditionnaly copies 0 to 31 bytes */ + movs r12, r2, lsl #28 + ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */ + ldmmiia r1!, {r8, r9} /* 8 bytes */ + stmcsia r0!, {r4, r5, r6, r7} + stmmiia r0!, {r8, r9} + movs r12, r2, lsl #30 + ldrcs r3, [r1], #4 /* 4 bytes */ + ldrmih r4, [r1], #2 /* 2 bytes */ + strcs r3, [r0], #4 + strmih r4, [r0], #2 + tst r2, #0x1 + ldrneb r3, [r1] /* last byte */ + strneb r3, [r0] + + /* we're done! restore everything and return */ +1: ldmfd sp!, {r5-r11} + ldmfd sp!, {r0, r4, lr} + bx lr + + /********************************************************************/ + +non_congruent: + /* + * here source is aligned to 4 bytes + * but destination is not. + * + * in the code below r2 is the number of bytes read + * (the number of bytes written is always smaller, because we have + * partial words in the shift queue) + */ + cmp r2, #4 + blo copy_last_3_and_return + + /* Use post-incriment mode for stm to spill r5-r11 to reserved stack + * frame. Don't update sp. + */ + stmea sp, {r5-r11} + + /* compute shifts needed to align src to dest */ + rsb r5, r0, #0 + and r5, r5, #3 /* r5 = # bytes in partial words */ + mov r12, r5, lsl #3 /* r12 = right */ + rsb lr, r12, #32 /* lr = left */ + + /* read the first word */ + ldr r3, [r1], #4 + sub r2, r2, #4 + + /* write a partial word (0 to 3 bytes), such that destination + * becomes aligned to 32 bits (r5 = nb of words to copy for alignment) + */ + movs r5, r5, lsl #31 + strmib r3, [r0], #1 + movmi r3, r3, lsr #8 + strcsb r3, [r0], #1 + movcs r3, r3, lsr #8 + strcsb r3, [r0], #1 + movcs r3, r3, lsr #8 + + cmp r2, #4 + blo partial_word_tail + + /* Align destination to 32 bytes (cache line boundary) */ +1: tst r0, #0x1c + beq 2f + ldr r5, [r1], #4 + sub r2, r2, #4 + orr r4, r3, r5, lsl lr + mov r3, r5, lsr r12 + str r4, [r0], #4 + cmp r2, #4 + bhs 1b + blo partial_word_tail + + /* copy 32 bytes at a time */ +2: subs r2, r2, #32 + blo less_than_thirtytwo + + /* Use immediate mode for the shifts, because there is an extra cycle + * for register shifts, which could account for up to 50% of + * performance hit. + */ + + cmp r12, #24 + beq loop24 + cmp r12, #8 + beq loop8 + +loop16: + ldr r12, [r1], #4 +1: mov r4, r12 + ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} + //PLD (r1, #64) + subs r2, r2, #32 + ldrhs r12, [r1], #4 + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7, lsl #16 + mov r7, r7, lsr #16 + orr r7, r7, r8, lsl #16 + mov r8, r8, lsr #16 + orr r8, r8, r9, lsl #16 + mov r9, r9, lsr #16 + orr r9, r9, r10, lsl #16 + mov r10, r10, lsr #16 + orr r10, r10, r11, lsl #16 + stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} + mov r3, r11, lsr #16 + bhs 1b + b less_than_thirtytwo + +loop8: + ldr r12, [r1], #4 +1: mov r4, r12 + ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} + //PLD (r1, #64) + subs r2, r2, #32 + ldrhs r12, [r1], #4 + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + mov r7, r7, lsr #8 + orr r7, r7, r8, lsl #24 + mov r8, r8, lsr #8 + orr r8, r8, r9, lsl #24 + mov r9, r9, lsr #8 + orr r9, r9, r10, lsl #24 + mov r10, r10, lsr #8 + orr r10, r10, r11, lsl #24 + stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} + mov r3, r11, lsr #8 + bhs 1b + b less_than_thirtytwo + +loop24: + ldr r12, [r1], #4 +1: mov r4, r12 + ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} + //PLD (r1, #64) + subs r2, r2, #32 + ldrhs r12, [r1], #4 + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + mov r7, r7, lsr #24 + orr r7, r7, r8, lsl #8 + mov r8, r8, lsr #24 + orr r8, r8, r9, lsl #8 + mov r9, r9, lsr #24 + orr r9, r9, r10, lsl #8 + mov r10, r10, lsr #24 + orr r10, r10, r11, lsl #8 + stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} + mov r3, r11, lsr #24 + bhs 1b + + +less_than_thirtytwo: + /* copy the last 0 to 31 bytes of the source */ + rsb r12, lr, #32 /* we corrupted r12, recompute it */ + add r2, r2, #32 + cmp r2, #4 + blo partial_word_tail + +1: ldr r5, [r1], #4 + sub r2, r2, #4 + orr r4, r3, r5, lsl lr + mov r3, r5, lsr r12 + str r4, [r0], #4 + cmp r2, #4 + bhs 1b + +partial_word_tail: + /* we have a partial word in the input buffer */ + movs r5, lr, lsl #(31-3) + strmib r3, [r0], #1 + movmi r3, r3, lsr #8 + strcsb r3, [r0], #1 + movcs r3, r3, lsr #8 + strcsb r3, [r0], #1 + + /* Refill spilled registers from the stack. Don't update sp. */ + ldmfd sp, {r5-r11} + +copy_last_3_and_return: + movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */ + ldrmib r2, [r1], #1 + ldrcsb r3, [r1], #1 + ldrcsb r12,[r1] + strmib r2, [r0], #1 + strcsb r3, [r0], #1 + strcsb r12,[r0] + + /* we're done! restore sp and spilled registers and return */ + add sp, sp, #28 + ldmfd sp!, {r0, r4, lr} + bx lr +#ifndef __APPLE__ + .fnend +#endif + +#endif /* __ARM_ARCH__ < 7 */ +#endif + +#if defined(__linux__) && defined(__ELF__) +/* we don't need an executable stack */ +.section .note.GNU-stack,"",%progbits +#endif diff --git a/xbmc/utils/fastmemcpy.c b/xbmc/utils/fastmemcpy.c new file mode 100644 index 0000000000000..ec9019ac7a9c5 --- /dev/null +++ b/xbmc/utils/fastmemcpy.c @@ -0,0 +1,396 @@ +/* + * fastmemcpy.h : fast memcpy routines + ***************************************************************************** + * $Id: fastmemcpy.h 13905 2006-01-12 23:10:04Z dionoea $ + * + * Authors: various Linux kernel hackers + * various MPlayer hackers + * Nick Kurshev + * + * Copyright (C) 2011-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#if !defined(TARGET_WINDOWS) && !defined(__ppc__) && !defined(__powerpc__) && !defined(__arm__) && !defined(__mips__) +#define HAVE_MMX2 +#define HAVE_SSE + +/* + aclib - advanced C library ;) + This file contains functions which improve and expand standard C-library +*/ +#include + +#define BLOCK_SIZE 4096 +#define CONFUSION_FACTOR 0 +/*Feel free to fine-tune the above 2, it might be possible to get some speedup with them :)*/ + +/*#define STATISTICS*/ + +#ifndef HAVE_SSE2 +/* + P3 processor has only one SSE decoder so can execute only 1 sse insn per + cpu clock, but it has 3 mmx decoders (include load/store unit) + and executes 3 mmx insns per cpu clock. + P4 processor has some chances, but after reading: + http://www.emulators.com/pentium4.htm + I have doubts. Anyway SSE2 version of this code can be written better. +*/ +#undef HAVE_SSE +#endif + + +/* + This part of code was taken by me from Linux-2.4.3 and slightly modified +for MMX, MMX2, SSE instruction set. I have done it since linux uses page aligned +blocks but mplayer uses weakly ordered data and original sources can not +speedup them. Only using PREFETCHNTA and MOVNTQ together have effect! + +>From IA-32 Intel Architecture Software Developer's Manual Volume 1, + +Order Number 245470: +"10.4.6. Cacheability Control, Prefetch, and Memory Ordering Instructions" + +Data referenced by a program can be temporal (data will be used again) or +non-temporal (data will be referenced once and not reused in the immediate +future). To make efficient use of the processor's caches, it is generally +desirable to cache temporal data and not cache non-temporal data. Overloading +the processor's caches with non-temporal data is sometimes referred to as +"polluting the caches". +The non-temporal data is written to memory with Write-Combining semantics. + +The PREFETCHh instructions permits a program to load data into the processor +at a suggested cache level, so that it is closer to the processors load and +store unit when it is needed. If the data is already present in a level of +the cache hierarchy that is closer to the processor, the PREFETCHh instruction +will not result in any data movement. +But we should you PREFETCHNTA: Non-temporal data fetch data into location +close to the processor, minimizing cache pollution. + +The MOVNTQ (store quadword using non-temporal hint) instruction stores +packed integer data from an MMX register to memory, using a non-temporal hint. +The MOVNTPS (store packed single-precision floating-point values using +non-temporal hint) instruction stores packed floating-point data from an +XMM register to memory, using a non-temporal hint. + +The SFENCE (Store Fence) instruction controls write ordering by creating a +fence for memory store operations. This instruction guarantees that the results +of every store instruction that precedes the store fence in program order is +globally visible before any store instruction that follows the fence. The +SFENCE instruction provides an efficient way of ensuring ordering between +procedures that produce weakly-ordered data and procedures that consume that +data. + +If you have questions please contact with me: Nick Kurshev: nickols_k@mail.ru. +*/ + +/* 3dnow memcpy support from kernel 2.4.2 */ +/* by Pontscho/fresh!mindworkz */ + +#if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW ) || defined( HAVE_MMX ) + +#undef HAVE_MMX1 +#if defined(HAVE_MMX) && !defined(HAVE_MMX2) && !defined(HAVE_3DNOW) && !defined(HAVE_SSE) +/* means: mmx v.1. Note: Since we added alignment of destinition it speedups + of memory copying on PentMMX, Celeron-1 and P2 upto 12% versus + standard (non MMX-optimized) version. + Note: on K6-2+ it speedups memory copying upto 25% and + on K7 and P3 about 500% (5 times). */ +#define HAVE_MMX1 +#endif + + +#undef HAVE_K6_2PLUS +#if !defined( HAVE_MMX2) && defined( HAVE_3DNOW) +#define HAVE_K6_2PLUS +#endif + +/* for small memory blocks (<256 bytes) this version is faster */ +#define small_memcpy(to,from,n)\ +{\ +register unsigned long int dummy;\ +__asm__ __volatile__(\ + "rep; movsb"\ + :"=&D"(to), "=&S"(from), "=&c"(dummy)\ +/* It's most portable way to notify compiler */\ +/* that edi, esi and ecx are clobbered in asm block. */\ +/* Thanks to A'rpi for hint!!! */\ + :"0" (to), "1" (from),"2" (n)\ + : "memory");\ +} + +#ifdef HAVE_SSE +#define MMREG_SIZE 16 +#else +#define MMREG_SIZE 64 /*8*/ +#endif + +/* Small defines (for readability only) ;) */ +#ifdef HAVE_K6_2PLUS +#define PREFETCH "prefetch" +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#define EMMS "femms" +#else +#define PREFETCH "prefetchnta" +#define EMMS "emms" +#endif + +#ifdef HAVE_MMX2 +#define MOVNTQ "movntq" +#else +#define MOVNTQ "movq" +#endif + +#ifdef HAVE_MMX1 +#define MIN_LEN 0x800 /* 2K blocks */ +#else +#define MIN_LEN 0x40 /* 64-byte blocks */ +#endif + +void * fast_memcpy(void * to, const void * from, size_t len) +{ + void *retval; + size_t i; + retval = to; +#ifdef STATISTICS + { + static int freq[33]; + static int t=0; + int i; + for(i=0; len>(1<= MIN_LEN) + { + register unsigned long int delta; + /* Align destinition to MMREG_SIZE -boundary */ + delta = ((unsigned long int)to)&(MMREG_SIZE-1); + if(delta) + { + delta=MMREG_SIZE-delta; + len -= delta; + small_memcpy(to, from, delta); + } + i = len >> 6; /* len/64 */ + len&=63; + /* + This algorithm is top effective when the code consequently + reads and writes blocks which have size of cache line. + Size of cache line is processor-dependent. + It will, however, be a minimum of 32 bytes on any processors. + It would be better to have a number of instructions which + perform reading and writing to be multiple to a number of + processor's decoders, but it's not always possible. + */ +#ifdef HAVE_SSE /* Only P3 (may be Cyrix3) */ + if(((unsigned long)from) & 15) + /* if SRC is misaligned */ + for(; i>0; i--) + { + __asm__ __volatile__ ( + PREFETCH" 320(%0)\n" + "movups (%0), %%xmm0\n" + "movups 16(%0), %%xmm1\n" + "movups 32(%0), %%xmm2\n" + "movups 48(%0), %%xmm3\n" + "movntps %%xmm0, (%1)\n" + "movntps %%xmm1, 16(%1)\n" + "movntps %%xmm2, 32(%1)\n" + "movntps %%xmm3, 48(%1)\n" + :: "r" (from), "r" (to) : "memory"); + ((const unsigned char *)from)+=64; + ((unsigned char *)to)+=64; + } + else + /* + Only if SRC is aligned on 16-byte boundary. + It allows to use movaps instead of movups, which required data + to be aligned or a general-protection exception (#GP) is generated. + */ + for(; i>0; i--) + { + __asm__ __volatile__ ( + PREFETCH" 320(%0)\n" + "movaps (%0), %%xmm0\n" + "movaps 16(%0), %%xmm1\n" + "movaps 32(%0), %%xmm2\n" + "movaps 48(%0), %%xmm3\n" + "movntps %%xmm0, (%1)\n" + "movntps %%xmm1, 16(%1)\n" + "movntps %%xmm2, 32(%1)\n" + "movntps %%xmm3, 48(%1)\n" + :: "r" (from), "r" (to) : "memory"); + ((const unsigned char *)from)+=64; + ((unsigned char *)to)+=64; + } +#else + /* Align destination at BLOCK_SIZE boundary */ + for(; ((ptrdiff_t)to & (BLOCK_SIZE-1)) && i>0; i--) + { + __asm__ __volatile__ ( +#ifndef HAVE_MMX1 + PREFETCH" 320(%0)\n" +#endif + "movq (%0), %%mm0\n" + "movq 8(%0), %%mm1\n" + "movq 16(%0), %%mm2\n" + "movq 24(%0), %%mm3\n" + "movq 32(%0), %%mm4\n" + "movq 40(%0), %%mm5\n" + "movq 48(%0), %%mm6\n" + "movq 56(%0), %%mm7\n" + MOVNTQ" %%mm0, (%1)\n" + MOVNTQ" %%mm1, 8(%1)\n" + MOVNTQ" %%mm2, 16(%1)\n" + MOVNTQ" %%mm3, 24(%1)\n" + MOVNTQ" %%mm4, 32(%1)\n" + MOVNTQ" %%mm5, 40(%1)\n" + MOVNTQ" %%mm6, 48(%1)\n" + MOVNTQ" %%mm7, 56(%1)\n" + :: "r" (from), "r" (to) : "memory"); + from = (const void *) (((const unsigned char *)from)+64); + to = (void *) (((unsigned char *)to)+64); + } + +/* printf(" %p %p\n", (ptrdiff_t)from&1023, (ptrdiff_t)to&1023); */ + /* Pure Assembly cuz gcc is a bit unpredictable ;) */ +# if 0 + if(i>=BLOCK_SIZE/64) + asm volatile( + "xorl %%eax, %%eax \n\t" + ".balign 16 \n\t" + "1: \n\t" + "movl (%0, %%eax), %%ebx \n\t" + "movl 32(%0, %%eax), %%ebx \n\t" + "movl 64(%0, %%eax), %%ebx \n\t" + "movl 96(%0, %%eax), %%ebx \n\t" + "addl $128, %%eax \n\t" + "cmpl %3, %%eax \n\t" + " jb 1b \n\t" + + "xorl %%eax, %%eax \n\t" + + ".balign 16 \n\t" + "2: \n\t" + "movq (%0, %%eax), %%mm0\n" + "movq 8(%0, %%eax), %%mm1\n" + "movq 16(%0, %%eax), %%mm2\n" + "movq 24(%0, %%eax), %%mm3\n" + "movq 32(%0, %%eax), %%mm4\n" + "movq 40(%0, %%eax), %%mm5\n" + "movq 48(%0, %%eax), %%mm6\n" + "movq 56(%0, %%eax), %%mm7\n" + MOVNTQ" %%mm0, (%1, %%eax)\n" + MOVNTQ" %%mm1, 8(%1, %%eax)\n" + MOVNTQ" %%mm2, 16(%1, %%eax)\n" + MOVNTQ" %%mm3, 24(%1, %%eax)\n" + MOVNTQ" %%mm4, 32(%1, %%eax)\n" + MOVNTQ" %%mm5, 40(%1, %%eax)\n" + MOVNTQ" %%mm6, 48(%1, %%eax)\n" + MOVNTQ" %%mm7, 56(%1, %%eax)\n" + "addl $64, %%eax \n\t" + "cmpl %3, %%eax \n\t" + "jb 2b \n\t" + +#if CONFUSION_FACTOR > 0 + /* a few percent speedup on out of order executing CPUs */ + "movl %5, %%eax \n\t" + "2: \n\t" + "movl (%0), %%ebx \n\t" + "movl (%0), %%ebx \n\t" + "movl (%0), %%ebx \n\t" + "movl (%0), %%ebx \n\t" + "decl %%eax \n\t" + " jnz 2b \n\t" +#endif + + "xorl %%eax, %%eax \n\t" + "addl %3, %0 \n\t" + "addl %3, %1 \n\t" + "subl %4, %2 \n\t" + "cmpl %4, %2 \n\t" + " jae 1b \n\t" + : "+r" (from), "+r" (to), "+r" (i) + : "r" (BLOCK_SIZE), "i" (BLOCK_SIZE/64), "i" (CONFUSION_FACTOR) + : "%eax", "%ebx" + ); +#endif + + for(; i>0; i--) + { + __asm__ __volatile__ ( +#ifndef HAVE_MMX1 + PREFETCH" 320(%0)\n" +#endif + "movq (%0), %%mm0\n" + "movq 8(%0), %%mm1\n" + "movq 16(%0), %%mm2\n" + "movq 24(%0), %%mm3\n" + "movq 32(%0), %%mm4\n" + "movq 40(%0), %%mm5\n" + "movq 48(%0), %%mm6\n" + "movq 56(%0), %%mm7\n" + MOVNTQ" %%mm0, (%1)\n" + MOVNTQ" %%mm1, 8(%1)\n" + MOVNTQ" %%mm2, 16(%1)\n" + MOVNTQ" %%mm3, 24(%1)\n" + MOVNTQ" %%mm4, 32(%1)\n" + MOVNTQ" %%mm5, 40(%1)\n" + MOVNTQ" %%mm6, 48(%1)\n" + MOVNTQ" %%mm7, 56(%1)\n" + :: "r" (from), "r" (to) : "memory"); + from = (const void *) (((const unsigned char *)from)+64); + to = (void *) (((unsigned char *)to)+64); + } + +#endif /* Have SSE */ +#ifdef HAVE_MMX2 + /* since movntq is weakly-ordered, a "sfence" + * is needed to become ordered again. */ + __asm__ __volatile__ ("sfence":::"memory"); +#endif +#ifndef HAVE_SSE + /* enables to use FPU */ + __asm__ __volatile__ (EMMS:::"memory"); +#endif + } + /* + * Now do the tail of the block + */ + if(len) small_memcpy(to, from, len); + return retval; +} + + +#endif /* #if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW ) || defined( HAVE_MMX ) */ + +#endif diff --git a/xbmc/utils/fastmemcpy.h b/xbmc/utils/fastmemcpy.h new file mode 100644 index 0000000000000..43f590464e67a --- /dev/null +++ b/xbmc/utils/fastmemcpy.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(TARGET_WINDOWS) && !defined(__ppc__) && !defined(__powerpc__) && !defined(__mips__) && !defined(TARGET_ANDROID) && !defined(TARGET_DARWIN_IOS) +void * fast_memcpy(void * to, const void * from, size_t len); +//#define fast_memcpy memcpy +#else +#define fast_memcpy memcpy +#endif + +#ifdef __cplusplus +} +#endif