1 #ifndef COMPOSITOR_H 2 #define COMPOSITOR_H 3 4 #include <vulkan/vulkan.h> 5 #include <vulkan/vulkan_xcb.h> 6 7 #include <xcb/composite.h> 8 #include <xcb/damage.h> 9 #include <xcb/shm.h> 10 #include <xcb/dri3.h> 11 12 #include <string> 13 14 //struct gbm_device; 15 16 namespace Backend{ 17 class X11Backend; 18 }; 19 20 namespace Compositor{ 21 22 class Drawable{ 23 friend class CompositorInterface; 24 public: 25 Drawable(Pipeline *, CompositorInterface *); 26 virtual ~Drawable(); 27 // 28 bool AssignPipeline(const Pipeline *); 29 protected: 30 void BindShaderResources(const std::vector<std::pair<ShaderModule::VARIABLE, const void *>> *, const VkCommandBuffer *); UpdateDescSets()31 virtual void UpdateDescSets(){}; 32 class CompositorInterface *pcomp; 33 struct PipelineDescriptorSet{ 34 uint64 fenceTag; 35 const Pipeline *p; 36 VkDescriptorSet *pdescSets[Pipeline::SHADER_MODULE_COUNT]; 37 }; 38 PipelineDescriptorSet *passignedSet; 39 std::vector<PipelineDescriptorSet> descSets; 40 }; 41 42 class ColorFrame : public Drawable{ 43 friend class CompositorInterface; 44 public: 45 ColorFrame(const char *[Pipeline::SHADER_MODULE_COUNT], class CompositorInterface *); 46 virtual ~ColorFrame(); 47 void Draw(const VkRect2D &, const glm::vec2 &, const glm::vec2 &, const glm::vec2 &, uint, uint, const VkCommandBuffer *); 48 protected: 49 struct timespec creationTime; 50 float time; 51 public: 52 uint shaderUserFlags; 53 protected: 54 uint shaderFlags; //current frame shader flags 55 uint oldShaderFlags; //used to keep track of changes 56 }; 57 58 class ClientFrame : public ColorFrame{ 59 friend class CompositorInterface; 60 friend class X11Compositor; 61 public: 62 ClientFrame(const char *[Pipeline::SHADER_MODULE_COUNT], class CompositorInterface *); 63 virtual ~ClientFrame(); 64 virtual void UpdateContents(const VkCommandBuffer *) = 0; 65 virtual void Exclude(bool); 66 void CreateSurface(uint, uint, uint); 67 void AdjustSurface(uint, uint); 68 void DestroySurface(); 69 void SetShaders(const char *[Pipeline::SHADER_MODULE_COUNT]); 70 void SetTitle(const char *); 71 enum SHADER_FLAG{ //+config 72 SHADER_FLAG_FOCUS = 0x1, 73 SHADER_FLAG_FLOATING = 0x2, 74 SHADER_FLAG_STACKED = 0x4, 75 SHADER_FLAG_USER_BIT = 0x8 76 }; 77 protected: 78 void UpdateDescSets(); 79 Texture *ptexture; 80 class Text *ptitle; 81 std::string title; 82 uint surfaceDepth; 83 public: 84 bool enabled; //in use and ready to draw 85 protected: 86 bool fullRegionUpdate; 87 bool animationCompleted; 88 }; 89 90 class CompositorInterface{ 91 friend class TextureBase; 92 friend class TextureStaged; 93 friend class TexturePixmap; 94 friend class TextureHostPointer; 95 friend class Texture; 96 friend class Buffer; 97 friend class ShaderModule; 98 friend class Pipeline; 99 friend class ClientPipeline; 100 friend class FontAtlas; 101 friend class Text; 102 friend class TextEngine; 103 friend class Drawable; 104 friend class ColorFrame; 105 friend class ClientFrame; 106 friend class X11ClientFrame; 107 friend class X11Background; 108 friend class X11DebugClientFrame; 109 public: 110 struct Configuration{ 111 uint deviceIndex; 112 bool debugLayers; 113 bool scissoring; 114 bool hostMemoryImport; 115 bool unredirOnFullscreen; 116 bool enableAnimation; 117 float animationDuration; 118 const char *pfontName; 119 uint fontSize; 120 }; 121 CompositorInterface(const Configuration *); 122 virtual ~CompositorInterface(); 123 virtual void Start() = 0; //initialize and start for the first time 124 virtual void Stop() = 0; //stop and cleanup 125 virtual void Resume() = 0; //resume after suspension 126 virtual void Suspend() = 0; //suspend (unredirection, for example) 127 protected: 128 void InitializeRenderEngine(); 129 void InitializeSwapchain(); 130 void DestroyRenderEngine(); 131 void DestroySwapchain(); 132 void AddShader(const char *, const Blob *); 133 void AddDamageRegion(const VkRect2D *); 134 void AddDamageRegion(const WManager::Client *); 135 void WaitIdle(); 136 void CreateRenderQueueAppendix(const WManager::Client *, const WManager::Container *); 137 void CreateRenderQueue(const WManager::Container *, const WManager::Container *); 138 bool PollFrameFence(bool); 139 void GenerateCommandBuffers(const WManager::Container *, const std::vector<std::pair<const WManager::Client *, WManager::Client *>> *, const WManager::Container *); 140 void Present(); 141 virtual bool CheckPresentQueueCompatibility(VkPhysicalDevice, uint) const = 0; 142 virtual void CreateSurfaceKHR(VkSurfaceKHR *) const = 0; 143 virtual VkExtent2D GetExtent() const = 0; 144 virtual glm::vec2 GetDPI() const = 0; 145 VkInstance instance; 146 VkSurfaceCapabilitiesKHR surfaceCapabilities; 147 VkSurfaceKHR surface; 148 VkDebugReportCallbackEXT debugReportCb; 149 VkPhysicalDevice physicalDev; 150 VkPhysicalDeviceProperties physicalDevProps; 151 VkPhysicalDeviceExternalMemoryHostPropertiesEXT physicalDevExternalMemoryHostProps; 152 VkDevice logicalDev; 153 enum QUEUE_INDEX{ 154 QUEUE_INDEX_GRAPHICS, 155 QUEUE_INDEX_PRESENT, 156 //QUEUE_INDEX_TRANSFER, 157 QUEUE_INDEX_COUNT 158 }; 159 VkQueue queue[QUEUE_INDEX_COUNT]; 160 VkRenderPass renderPass; 161 VkSwapchainKHR swapChain; 162 VkExtent2D imageExtent; 163 VkImage *pswapChainImages; 164 VkImageView *pswapChainImageViews; 165 VkFramebuffer *pframebuffers; 166 enum SEMAPHORE_INDEX{ 167 SEMAPHORE_INDEX_IMAGE_AVAILABLE, 168 SEMAPHORE_INDEX_RENDER_FINISHED, 169 SEMAPHORE_INDEX_COUNT 170 }; 171 VkSemaphore (*psemaphore)[SEMAPHORE_INDEX_COUNT]; 172 VkFence *pfence; 173 //back buffer to enable the use of previous frame contents 174 //VkImage renderImage; 175 //VkDeviceMemory renderImageDeviceMemory; 176 177 VkCommandPool commandPool; 178 VkCommandBuffer *pcommandBuffers; 179 VkCommandBuffer *pcopyCommandBuffers; 180 181 //VkDescriptorPool descPool; 182 std::deque<VkDescriptorPool> descPoolArray; 183 std::vector<std::pair<VkDescriptorSet *, VkDescriptorPool>> descPoolReference; 184 185 uint queueFamilyIndex[QUEUE_INDEX_COUNT]; // 186 uint physicalDevIndex; 187 uint swapChainImageCount; 188 uint currentFrame; 189 uint imageIndex; 190 191 template<class T> 192 Pipeline * LoadPipeline(const char *[Pipeline::SHADER_MODULE_COUNT], const std::vector<std::pair<ShaderModule::INPUT,uint>> *); 193 194 std::vector<ShaderModule> shaders; 195 std::vector<std::pair<size_t, Pipeline *>> pipelines; //hash, pipeline 196 197 std::vector<ClientFrame *> updateQueue; 198 std::vector<ClientFrame *> titleUpdateQueue; 199 //Scissoring regions based on client damage. Second (uint) is a bitmask for 200 //swap chain images, indicating which image has been updated so far. When 201 //all images have been updated, the region is removed from the list. 202 std::vector<std::pair<VkRect2D, uint>> scissorRegions; 203 std::vector<VkRectLayerKHR> presentRectLayers; 204 205 void ClearBackground(); 206 207 ColorFrame *pcolorBackground; 208 ColorFrame *pbackground; 209 public: 210 class TextEngine *ptextEngine; 211 const char *pfontName; 212 uint fontSize; 213 protected: 214 215 VkSampler pointSampler; 216 217 struct timespec frameTime; 218 uint64 frameTag; //frame counter, to prevent releasing resources still in use 219 220 struct RenderObject{ 221 WManager::Client *pclient; 222 ClientFrame *pclientFrame; 223 //uint flags; 224 }; 225 std::vector<RenderObject> renderQueue; 226 227 typedef std::tuple<const WManager::Client *, WManager::Client *, ClientFrame *> AppendixQueueElement; 228 std::deque<AppendixQueueElement> appendixQueue; 229 230 //Used textures get stored for potential reuse before they get destroyed and while waiting for the pipeline to get flushed. 231 //Many of the allocated window textures will initially have some common reoccuring size. 232 Texture * CreateTexture(uint, uint, uint); 233 void ReleaseTexture(Texture *); 234 235 struct TextureCacheEntry{ 236 Texture *ptexture; 237 uint64 releaseTag; 238 struct timespec releaseTime; 239 }; 240 std::vector<TextureCacheEntry> textureCache; 241 242 VkDescriptorSet * CreateDescSets(const ShaderModule *); 243 void ReleaseDescSets(const ShaderModule *, VkDescriptorSet *); 244 245 struct DescSetCacheEntry{ 246 VkDescriptorSet *pdescSets; 247 uint setCount; 248 uint64 releaseTag; 249 }; 250 std::vector<DescSetCacheEntry> descSetCache; 251 252 ClientFrame *pfsApp; //fullscreen state app for the current frame (for unredirection) 253 ClientFrame *pfsAppPrev; //fullscreen state app during previous frame (for unredirection) 254 bool frameApproval; 255 bool suspended; //entire compositor is suspended - all windows are unredirected 256 bool unredirected; //one of the applications is underirected due to it being fullscreen 257 bool playingAnimation; 258 259 //config 260 bool debugLayers; 261 bool scissoring; 262 bool hostMemoryImport; 263 bool unredirOnFullscreen; 264 265 public: 266 bool enableAnimation; 267 float animationDuration; 268 protected: 269 270 static VKAPI_ATTR VkBool32 VKAPI_CALL ValidationLayerDebugCallback(VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t, const char *, const char *, void *); 271 static VKAPI_ATTR VkBool32 VKAPI_CALL ValidationLayerDebugCallback2(VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *, void *); 272 }; 273 274 class X11ClientFrame : public Backend::X11Client, public ClientFrame{ 275 public: 276 X11ClientFrame(Backend::X11Container *, const Backend::X11Client::CreateInfo *, const char *[Pipeline::SHADER_MODULE_COUNT], CompositorInterface *); 277 ~X11ClientFrame(); 278 void UpdateContents(const VkCommandBuffer *); 279 void Exclude(bool); 280 void AdjustSurface1(); 281 void Redirect1(); 282 void StartComposition1(); 283 void Unredirect1(); 284 void StopComposition1(); 285 void SetTitle1(const char *); 286 xcb_pixmap_t windowPixmap; 287 xcb_shm_seg_t segment; 288 xcb_damage_damage_t damage; 289 std::vector<VkRect2D> damageRegions; 290 sint shmid; 291 unsigned char *pchpixels; 292 }; 293 294 class X11Background : public ClientFrame{ 295 public: 296 X11Background(xcb_pixmap_t, uint, uint, const char *[Pipeline::SHADER_MODULE_COUNT], X11Compositor *); 297 ~X11Background(); 298 void UpdateContents(const VkCommandBuffer *); 299 300 X11Compositor *pcomp11; 301 xcb_pixmap_t pixmap; 302 xcb_shm_seg_t segment; 303 uint w, h; 304 sint shmid; 305 unsigned char *pchpixels; 306 }; 307 308 //Default compositor assumes XCB for its surface 309 class X11Compositor : public CompositorInterface{ 310 friend class TexturePixmap; 311 public: 312 //Derivatives of compositor classes should not point to their default corresponding backend classes (Backend::Default in this case). This is to allow the compositor to be independent of the backend implementation, as long as it's based on X11 here. 313 X11Compositor(const Configuration *, const Backend::X11Backend *); 314 ~X11Compositor(); 315 virtual void Start(); 316 virtual void Stop(); 317 virtual void Resume(); 318 virtual void Suspend(); 319 bool FilterEvent(const Backend::X11Event *); 320 bool CheckPresentQueueCompatibility(VkPhysicalDevice, uint) const; 321 void CreateSurfaceKHR(VkSurfaceKHR *) const; 322 void SetBackgroundPixmap(const Backend::BackendPixmapProperty *); 323 VkExtent2D GetExtent() const; 324 glm::vec2 GetDPI() const; 325 const Backend::X11Backend *pbackend; 326 /*struct gbm_device *pgbmdev; 327 sint cardfd;*/ 328 xcb_window_t overlay; 329 protected: 330 sint compEventOffset; 331 sint compErrorOffset; 332 sint xfixesEventOffset; 333 sint xfixesErrorOffset; 334 sint damageEventOffset; 335 sint damageErrorOffset; 336 }; 337 338 class X11DebugClientFrame : public Backend::DebugClient, public ClientFrame{ 339 public: 340 X11DebugClientFrame(Backend::DebugContainer *, const Backend::DebugClient::CreateInfo *, const char *[Pipeline::SHADER_MODULE_COUNT], CompositorInterface *); 341 ~X11DebugClientFrame(); 342 void UpdateContents(const VkCommandBuffer *); 343 void AdjustSurface1(); 344 void Redirect1(); 345 void StartComposition1(); 346 void Unredirect1(); 347 void StopComposition1(); 348 void SetTitle1(const char *); 349 }; 350 351 class X11DebugCompositor : public X11Compositor{ 352 public: 353 X11DebugCompositor(const Configuration *, const Backend::X11Backend *); 354 ~X11DebugCompositor(); 355 void Start(); 356 void Stop(); 357 void Resume(); 358 void Suspend(); 359 }; 360 361 class NullCompositor : public CompositorInterface{ 362 public: 363 NullCompositor(); 364 ~NullCompositor(); 365 void Start(); 366 void Stop(); 367 void Resume(); 368 void Suspend(); 369 bool CheckPresentQueueCompatibility(VkPhysicalDevice, uint) const; 370 void CreateSurfaceKHR(VkSurfaceKHR *) const; 371 VkExtent2D GetExtent() const; 372 glm::vec2 GetDPI() const; 373 Configuration config{ //dummy config 374 .deviceIndex = 0, 375 .debugLayers = false, 376 .scissoring = true, 377 .hostMemoryImport = true, 378 .enableAnimation = false, 379 .animationDuration = 0.3f, 380 .pfontName = "Monospace", 381 .fontSize = 18, 382 }; 383 }; 384 385 } 386 387 #endif 388 389