1 #include "main.h"
2 #include "container.h"
3 #include "backend.h"
4 #include "CompositorResource.h"
5 #include "compositor.h"
6 #include "CompositorFont.h"
7
8 #include <algorithm>
9 #include <cstdlib>
10 #include <limits>
11 #include <sys/shm.h>
12 #include <boost/container_hash/hash.hpp>
13
14 //#include <gbm.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17
18 namespace Compositor{
19
Drawable(Pipeline * pPipeline,CompositorInterface * _pcomp)20 Drawable::Drawable(Pipeline *pPipeline, CompositorInterface *_pcomp) : pcomp(_pcomp), passignedSet(0){
21 if(!AssignPipeline(pPipeline))
22 throw Exception("Failed to assign a pipeline");
23 }
24
~Drawable()25 Drawable::~Drawable(){
26 for(PipelineDescriptorSet &pipelineDescSet : descSets)
27 for(uint i = 0; i < Pipeline::SHADER_MODULE_COUNT; ++i)
28 if(pipelineDescSet.p->pshaderModule[i] && pipelineDescSet.pdescSets[i])
29 pcomp->ReleaseDescSets(pipelineDescSet.p->pshaderModule[i],pipelineDescSet.pdescSets[i]);
30 }
31
AssignPipeline(const Pipeline * prenderPipeline)32 bool Drawable::AssignPipeline(const Pipeline *prenderPipeline){
33 auto m = std::find_if(descSets.begin(),descSets.end(),[&](auto &r)->bool{
34 return r.p == prenderPipeline && pcomp->frameTag > r.fenceTag+pcomp->swapChainImageCount+1;
35 });
36 if(m != descSets.end()){
37 passignedSet = &(*m);
38 return true;
39 }
40
41 PipelineDescriptorSet pipelineDescSet;
42 pipelineDescSet.fenceTag = pcomp->frameTag;
43 pipelineDescSet.p = prenderPipeline;
44 for(uint i = 0; i < Pipeline::SHADER_MODULE_COUNT; ++i){
45 if(!prenderPipeline->pshaderModule[i])
46 continue;
47 if(!prenderPipeline->pshaderModule[i] || prenderPipeline->pshaderModule[i]->setCount == 0){
48 pipelineDescSet.pdescSets[i] = 0;
49 continue;
50 }
51 pipelineDescSet.pdescSets[i] = pcomp->CreateDescSets(prenderPipeline->pshaderModule[i]);
52 if(!pipelineDescSet.pdescSets[i])
53 return false;
54 }
55 descSets.push_back(pipelineDescSet);
56 passignedSet = &descSets.back();
57
58 return true;
59 }
60
BindShaderResources(const std::vector<std::pair<ShaderModule::VARIABLE,const void * >> * pVarAddrs,const VkCommandBuffer * pcommandBuffer)61 void Drawable::BindShaderResources(const std::vector<std::pair<ShaderModule::VARIABLE, const void *>> *pVarAddrs, const VkCommandBuffer *pcommandBuffer){
62 alignas(16) char pushConstantBuffer[128];
63 for(uint i = 0, p = 0; i < Pipeline::SHADER_MODULE_COUNT; ++i){
64 //bind descriptor sets
65 if(!passignedSet->p->pshaderModule[i])
66 continue;
67 if(passignedSet->p->pshaderModule[i]->setCount > 0){
68 vkCmdBindDescriptorSets(*pcommandBuffer,VK_PIPELINE_BIND_POINT_GRAPHICS,passignedSet->p->pipelineLayout,p,passignedSet->p->pshaderModule[i]->setCount,passignedSet->pdescSets[i],0,0);
69 p += passignedSet->p->pshaderModule[i]->setCount;
70 }
71 //copy push constants
72 for(uint j = 0; j < passignedSet->p->pshaderModule[i]->variables.size(); ++j){
73 auto m = std::find_if(pVarAddrs->begin(),pVarAddrs->end(),[&](auto &r)->bool{
74 return (uint)r.first == passignedSet->p->pshaderModule[i]->variables[j].variableMapIndex;
75 });
76 if(m == pVarAddrs->end())
77 continue;
78 //printf("var: %s, +%u\n",std::get<0>(ShaderModule::variableMap[passignedSet->p->pshaderModule[i]->variables[j].variableMapIndex]),passignedSet->p->pshaderModule[i]->variables[j].offset);
79 memcpy(pushConstantBuffer+passignedSet->p->pshaderModule[i]->variables[j].offset,
80 m->second,std::get<1>(ShaderModule::variableMap[passignedSet->p->pshaderModule[i]->variables[j].variableMapIndex]));
81 }
82 }
83
84 if(passignedSet->p->pushConstantRange.size > 0)
85 vkCmdPushConstants(*pcommandBuffer,passignedSet->p->pipelineLayout,passignedSet->p->pushConstantRange.stageFlags,passignedSet->p->pushConstantRange.offset,passignedSet->p->pushConstantRange.size,pushConstantBuffer);
86 }
87
ColorFrame(const char * pshaderName[Pipeline::SHADER_MODULE_COUNT],CompositorInterface * _pcomp)88 ColorFrame::ColorFrame(const char *pshaderName[Pipeline::SHADER_MODULE_COUNT], CompositorInterface *_pcomp) : Drawable(_pcomp->LoadPipeline<ClientPipeline>(pshaderName,0),_pcomp), shaderUserFlags(0), shaderFlags(0), oldShaderFlags(0){
89 //
90 clock_gettime(CLOCK_MONOTONIC,&creationTime);
91 }
92
~ColorFrame()93 ColorFrame::~ColorFrame(){
94 //
95 }
96
Draw(const VkRect2D & frame,const glm::vec2 & margin,const glm::vec2 & titlePad,const glm::vec2 & titleSpan,uint stackIndex,uint flags,const VkCommandBuffer * pcommandBuffer)97 void ColorFrame::Draw(const VkRect2D &frame, const glm::vec2 &margin, const glm::vec2 &titlePad, const glm::vec2 &titleSpan, uint stackIndex, uint flags, const VkCommandBuffer *pcommandBuffer){
98 time = timespec_diff(pcomp->frameTime,creationTime);
99
100 glm::vec2 imageExtent = glm::vec2(pcomp->imageExtent.width,pcomp->imageExtent.height);
101
102 glm::vec4 frameVec = {frame.offset.x,frame.offset.y,
103 frame.offset.x+frame.extent.width,frame.offset.y+frame.extent.height};
104 frameVec = 2.0f*(frameVec+0.5f)/glm::vec4(imageExtent,imageExtent)-1.0f;
105
106 std::vector<std::pair<ShaderModule::VARIABLE, const void *>> varAddrs = {
107 {ShaderModule::VARIABLE_XY0,&frameVec},
108 {ShaderModule::VARIABLE_XY1,&frameVec.z},
109 {ShaderModule::VARIABLE_SCREEN,&imageExtent},
110 {ShaderModule::VARIABLE_MARGIN,&margin},
111 {ShaderModule::VARIABLE_TITLEPAD,&titlePad},
112 {ShaderModule::VARIABLE_TITLESPAN,&titleSpan},
113 {ShaderModule::VARIABLE_STACKINDEX,&stackIndex},
114 {ShaderModule::VARIABLE_FLAGS,&flags},
115 {ShaderModule::VARIABLE_TIME,&time}
116 };
117 BindShaderResources(&varAddrs,pcommandBuffer);
118
119 vkCmdDraw(*pcommandBuffer,1,1,0,0);
120
121 passignedSet->fenceTag = pcomp->frameTag;
122 }
123
ClientFrame(const char * pshaderName[Pipeline::SHADER_MODULE_COUNT],CompositorInterface * _pcomp)124 ClientFrame::ClientFrame(const char *pshaderName[Pipeline::SHADER_MODULE_COUNT], CompositorInterface *_pcomp) : ColorFrame(pshaderName,_pcomp), ptitle(0), fullRegionUpdate(true), animationCompleted(true), enabled(false){
125 //
126 }
127
~ClientFrame()128 ClientFrame::~ClientFrame(){
129 if(ptitle)
130 delete ptitle;
131 pcomp->updateQueue.erase(std::remove(pcomp->updateQueue.begin(),pcomp->updateQueue.end(),this),pcomp->updateQueue.end());
132 pcomp->titleUpdateQueue.erase(std::remove(pcomp->titleUpdateQueue.begin(),pcomp->titleUpdateQueue.end(),this),pcomp->titleUpdateQueue.end());
133 }
134
Exclude(bool exclude)135 void ClientFrame::Exclude(bool exclude){
136 //
137 }
138
CreateSurface(uint w,uint h,uint depth)139 void ClientFrame::CreateSurface(uint w, uint h, uint depth){
140 pcomp->updateQueue.push_back(this);
141
142 surfaceDepth = depth;
143 ptexture = pcomp->CreateTexture(w,h,surfaceDepth);
144
145 UpdateDescSets();
146 }
147
AdjustSurface(uint w,uint h)148 void ClientFrame::AdjustSurface(uint w, uint h){
149 pcomp->ReleaseTexture(ptexture);
150
151 pcomp->updateQueue.push_back(this);
152 fullRegionUpdate = true;
153
154 ptexture = pcomp->CreateTexture(w,h,surfaceDepth);
155 //In this case updating the descriptor sets would be enough, but we can't do that because of them being used currently by the pipeline.
156 if(!AssignPipeline(passignedSet->p))
157 throw Exception("Failed to assign a pipeline.");
158 DebugPrintf(stdout,"Texture created: %ux%u\n",w,h);
159
160 UpdateDescSets();
161 }
162
DestroySurface()163 void ClientFrame::DestroySurface(){
164 //
165 pcomp->ReleaseTexture(ptexture);
166 }
167
SetShaders(const char * pshaderName[Pipeline::SHADER_MODULE_COUNT])168 void ClientFrame::SetShaders(const char *pshaderName[Pipeline::SHADER_MODULE_COUNT]){
169 Pipeline *pPipeline = pcomp->LoadPipeline<ClientPipeline>(pshaderName,0);
170 if(!AssignPipeline(pPipeline))
171 throw Exception("Failed to assign a pipeline.");
172
173 UpdateDescSets();
174 }
175
SetTitle(const char * ptext)176 void ClientFrame::SetTitle(const char *ptext){
177 if(!ptitle){
178 static const char *pshaderName[Pipeline::SHADER_MODULE_COUNT] = {
179 "text_vertex.spv",0,"text_fragment.spv"
180 };
181 ptitle = new Text(pshaderName,pcomp->ptextEngine);
182 }
183 title = ptext;
184 pcomp->titleUpdateQueue.push_back(this);
185 }
186
UpdateDescSets()187 void ClientFrame::UpdateDescSets(){
188 //
189 VkDescriptorImageInfo descImageInfo = {};
190 descImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
191 descImageInfo.imageView = ptexture->imageView;
192 descImageInfo.sampler = pcomp->pointSampler;
193
194 std::vector<VkWriteDescriptorSet> writeDescSets;
195 for(uint i = 0; i < Pipeline::SHADER_MODULE_COUNT; ++i){
196 if(!passignedSet->p->pshaderModule[i])
197 continue;
198 auto m1 = std::find_if(passignedSet->p->pshaderModule[i]->bindings.begin(),passignedSet->p->pshaderModule[i]->bindings.end(),[&](auto &r)->bool{
199 return r.type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE && strcmp(r.pname,"content") == 0;
200 });
201 if(m1 != passignedSet->p->pshaderModule[i]->bindings.end()){
202 VkWriteDescriptorSet &writeDescSet = writeDescSets.emplace_back();
203 writeDescSet = (VkWriteDescriptorSet){};
204 writeDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
205 writeDescSet.dstSet = passignedSet->pdescSets[i][(*m1).setIndex];
206 writeDescSet.dstBinding = (*m1).binding;
207 writeDescSet.dstArrayElement = 0;
208 writeDescSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
209 writeDescSet.descriptorCount = 1;
210 writeDescSet.pImageInfo = &descImageInfo;
211 }
212
213 auto m2 = std::find_if(passignedSet->p->pshaderModule[i]->bindings.begin(),passignedSet->p->pshaderModule[i]->bindings.end(),[&](auto &r)->bool{
214 return r.type == VK_DESCRIPTOR_TYPE_SAMPLER;
215 });
216 if(m2 != passignedSet->p->pshaderModule[i]->bindings.end()){
217 VkWriteDescriptorSet &writeDescSet = writeDescSets.emplace_back();
218 writeDescSet = (VkWriteDescriptorSet){};
219 writeDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
220 writeDescSet.dstSet = passignedSet->pdescSets[i][(*m2).setIndex];
221 writeDescSet.dstBinding = (*m2).binding;
222 writeDescSet.dstArrayElement = 0;
223 writeDescSet.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
224 writeDescSet.descriptorCount = 1;
225 writeDescSet.pImageInfo = &descImageInfo;
226 }
227 }
228 vkUpdateDescriptorSets(pcomp->logicalDev,writeDescSets.size(),writeDescSets.data(),0,0);
229 }
230
CompositorInterface(const Configuration * pconfig)231 CompositorInterface::CompositorInterface(const Configuration *pconfig) : physicalDevIndex(pconfig->deviceIndex), currentFrame(0), imageIndex(0), frameTag(0), pcolorBackground(0), pbackground(0), ptextEngine(0), pfsApp(0), pfsAppPrev(0), frameApproval(false), suspended(false), unredirected(false), playingAnimation(false), debugLayers(pconfig->debugLayers), scissoring(pconfig->scissoring), hostMemoryImport(pconfig->hostMemoryImport), unredirOnFullscreen(pconfig->unredirOnFullscreen), enableAnimation(pconfig->enableAnimation), animationDuration(pconfig->animationDuration), pfontName(pconfig->pfontName), fontSize(pconfig->fontSize){
232 //
233 }
234
~CompositorInterface()235 CompositorInterface::~CompositorInterface(){
236 //
237 }
238
InitializeRenderEngine()239 void CompositorInterface::InitializeRenderEngine(){
240 uint layerCount;
241 vkEnumerateInstanceLayerProperties(&layerCount,0);
242 VkLayerProperties *playerProps = new VkLayerProperties[layerCount];
243 vkEnumerateInstanceLayerProperties(&layerCount,playerProps);
244
245 const char *players[] = {"VK_LAYER_KHRONOS_validation"};
246 DebugPrintf(stdout,"Enumerating required layers\n");
247 uint layersFound = 0;
248 for(uint i = 0; i < layerCount; ++i)
249 for(uint j = 0; j < sizeof(players)/sizeof(players[0]); ++j)
250 if(strcmp(playerProps[i].layerName,players[j]) == 0){
251 printf(" %s\n",players[j]);
252 ++layersFound;
253 }
254 if(debugLayers && layersFound < sizeof(players)/sizeof(players[0]))
255 throw Exception("Could not find all required layers.");
256
257 uint extCount;
258 vkEnumerateInstanceExtensionProperties(0,&extCount,0);
259 VkExtensionProperties *pextProps = new VkExtensionProperties[extCount];
260 vkEnumerateInstanceExtensionProperties(0,&extCount,pextProps);
261
262 const char *pextensions[] = {
263 VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
264 "VK_KHR_surface",
265 "VK_KHR_xcb_surface",
266 "VK_KHR_get_physical_device_properties2",
267 "VK_KHR_external_memory_capabilities"
268 };
269 DebugPrintf(stdout,"Enumerating required extensions\n");
270 uint extFound = 0;
271 for(uint i = 0; i < extCount; ++i)
272 for(uint j = 0; j < sizeof(pextensions)/sizeof(pextensions[0]); ++j)
273 if(strcmp(pextProps[i].extensionName,pextensions[j]) == 0){
274 printf(" %s\n",pextensions[j]);
275 ++extFound;
276 }
277 if(extFound < sizeof(pextensions)/sizeof(pextensions[0]))
278 throw Exception("Could not find all required extensions.");
279
280 VkApplicationInfo appInfo = {};
281 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
282 appInfo.pApplicationName = "chamferwm";
283 appInfo.applicationVersion = VK_MAKE_VERSION(0,0,1);
284 appInfo.pEngineName = "chamferwm-engine";
285 appInfo.engineVersion = VK_MAKE_VERSION(0,0,1);
286 appInfo.apiVersion = VK_API_VERSION_1_0;
287
288 VkDebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfo = {};
289 debugUtilsMessengerCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
290 debugUtilsMessengerCreateInfo.messageSeverity
291 = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
292 |VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
293 |VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
294 |VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
295 debugUtilsMessengerCreateInfo.messageType
296 = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
297 |VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
298 |VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
299 debugUtilsMessengerCreateInfo.pfnUserCallback = ValidationLayerDebugCallback2;
300
301 VkInstanceCreateInfo instanceCreateInfo = {};
302 instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
303 instanceCreateInfo.pApplicationInfo = &appInfo;
304 if(debugLayers){
305 DebugPrintf(stdout,"Debug layers enabled.\n");
306 //also in vkCreateDevice
307 instanceCreateInfo.enabledLayerCount = sizeof(players)/sizeof(players[0]);
308 instanceCreateInfo.ppEnabledLayerNames = players;
309 }else{
310 instanceCreateInfo.enabledLayerCount = 0;
311 instanceCreateInfo.ppEnabledLayerNames = 0;
312 }
313 instanceCreateInfo.enabledExtensionCount = sizeof(pextensions)/sizeof(pextensions[0]);
314 instanceCreateInfo.ppEnabledExtensionNames = pextensions;
315 instanceCreateInfo.pNext = &debugUtilsMessengerCreateInfo;
316 if(vkCreateInstance(&instanceCreateInfo,0,&instance) != VK_SUCCESS)
317 throw Exception("Failed to create Vulkan instance.");
318
319 //delete []playerProps;
320 delete []pextProps;
321
322 CreateSurfaceKHR(&surface);
323
324 VkDebugReportCallbackCreateInfoEXT debugcbCreateInfo = {};
325 debugcbCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
326 debugcbCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT|VK_DEBUG_REPORT_WARNING_BIT_EXT;
327 debugcbCreateInfo.pfnCallback = ValidationLayerDebugCallback;
328 ((PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance,"vkCreateDebugReportCallbackEXT"))(instance,&debugcbCreateInfo,0,&debugReportCb);
329
330 DebugPrintf(stdout,"Enumerating physical devices\n");
331
332 //physical device
333 uint devCount;
334 vkEnumeratePhysicalDevices(instance,&devCount,0);
335 VkPhysicalDevice *pdevices = new VkPhysicalDevice[devCount];
336 vkEnumeratePhysicalDevices(instance,&devCount,pdevices);
337
338 //VkPhysicalDeviceProperties *pdevProps = new VkPhysicalDeviceProperties[devCount];
339 VkPhysicalDeviceExternalMemoryHostPropertiesEXT *pPhysicalDeviceExternalMemoryHostProps = new VkPhysicalDeviceExternalMemoryHostPropertiesEXT[devCount];
340 VkPhysicalDeviceProperties2 *pdevProps = new VkPhysicalDeviceProperties2[devCount];
341 for(uint i = 0; i < devCount; ++i){
342 //device properties
343 pPhysicalDeviceExternalMemoryHostProps[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
344 pPhysicalDeviceExternalMemoryHostProps[i].pNext = 0;
345
346 pdevProps[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
347 pdevProps[i].pNext = &pPhysicalDeviceExternalMemoryHostProps[i];
348 vkGetPhysicalDeviceProperties2(pdevices[i],&pdevProps[i]);
349
350 //device features
351 VkPhysicalDeviceFeatures devFeatures;
352 vkGetPhysicalDeviceFeatures(pdevices[i],&devFeatures);
353
354 //extra checks
355 VkPhysicalDeviceExternalBufferInfo physicalDeviceExternalBufferInfo = {};
356 physicalDeviceExternalBufferInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO;
357 physicalDeviceExternalBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
358 physicalDeviceExternalBufferInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
359 VkExternalBufferProperties externalBufferProps = {};
360 externalBufferProps.sType = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES;
361 vkGetPhysicalDeviceExternalBufferProperties(pdevices[i],&physicalDeviceExternalBufferInfo,&externalBufferProps);
362 if((externalBufferProps.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) && (externalBufferProps.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0 && (externalBufferProps.externalMemoryProperties.compatibleHandleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT))
363 printf("Host pointer import supported!\n");
364
365 printf("%c %u: %s\n\t.deviceID: %u\n\t.vendorID: %u\n\t.deviceType: %u\n",
366 i == physicalDevIndex?'*':' ',
367 i,pdevProps[i].properties.deviceName,pdevProps[i].properties.deviceID,pdevProps[i].properties.vendorID,pdevProps[i].properties.deviceType);
368 printf(" max push constant size: %u\n max bound desc sets: %u\n",
369 pdevProps[i].properties.limits.maxPushConstantsSize,pdevProps[i].properties.limits.maxBoundDescriptorSets);
370 }
371
372 if(physicalDevIndex >= devCount){
373 snprintf(Exception::buffer,sizeof(Exception::buffer),"Invalid gpu-index (%u) exceeds the number of available devices (%u).",physicalDevIndex,devCount);
374 throw Exception();
375 }
376
377 physicalDev = pdevices[physicalDevIndex];
378 physicalDevExternalMemoryHostProps = pPhysicalDeviceExternalMemoryHostProps[physicalDevIndex];
379 physicalDevProps = pdevProps[physicalDevIndex].properties;
380
381 delete []pdevices;
382 delete []pdevProps;
383 delete []pPhysicalDeviceExternalMemoryHostProps;
384
385 //VkSurfaceCapabilitiesKHR surfaceCapabilities;
386 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDev,surface,&surfaceCapabilities);
387
388 uint formatCount;
389 vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDev,surface,&formatCount,0);
390 VkSurfaceFormatKHR *pformats = new VkSurfaceFormatKHR[formatCount];
391 vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDev,surface,&formatCount,pformats);
392
393 DebugPrintf(stdout,"Available surface formats: %u\n",formatCount);
394 for(uint i = 0; i < formatCount; ++i)
395 if(pformats[i].format == VK_FORMAT_B8G8R8A8_UNORM && pformats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
396 printf("Surface format ok.\n");
397
398 uint presentModeCount;
399 vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDev,surface,&presentModeCount,0);
400 VkPresentModeKHR *ppresentModes = new VkPresentModeKHR[presentModeCount];
401 vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDev,surface,&presentModeCount,ppresentModes);
402
403 uint queueFamilyCount;
404 vkGetPhysicalDeviceQueueFamilyProperties(physicalDev,&queueFamilyCount,0);
405 VkQueueFamilyProperties *pqueueFamilyProps = new VkQueueFamilyProperties[queueFamilyCount];
406 vkGetPhysicalDeviceQueueFamilyProperties(physicalDev,&queueFamilyCount,pqueueFamilyProps);
407
408 //find required queue families
409 for(uint i = 0; i < QUEUE_INDEX_COUNT; ++i)
410 queueFamilyIndex[i] = ~0u;
411 for(uint i = 0; i < queueFamilyCount; ++i){
412 if(pqueueFamilyProps[i].queueCount > 0 && pqueueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT){
413 queueFamilyIndex[QUEUE_INDEX_GRAPHICS] = i;
414 break;
415 }
416 }
417 for(uint i = 0; i < queueFamilyCount; ++i){
418 VkBool32 presentSupport;
419 vkGetPhysicalDeviceSurfaceSupportKHR(physicalDev,i,surface,&presentSupport);
420
421 bool compatible = CheckPresentQueueCompatibility(physicalDev,i);
422 //printf("Device compatibility:\t%u\nPresent support:\t%u\n",compatible,presentSupport);
423 if(pqueueFamilyProps[i].queueCount > 0 && compatible && presentSupport){
424 queueFamilyIndex[QUEUE_INDEX_PRESENT] = i;
425 break;
426 }
427 }
428 /*for(uint i = 0; i < queueFamilyCount; ++i){
429 if(pqueueFamilyProps[i].queueCount > 0 && pqueueFamilyProps[i].queueFlags & VK_QUEUE_TRANSFER_BIT){
430 queueFamilyIndex[QUEUE_INDEX_TRANSFER] = i;
431 break;
432 }
433 }*/
434 std::set<uint> queueSet;
435 for(uint i = 0; i < QUEUE_INDEX_COUNT; ++i){
436 if(queueFamilyIndex[i] == ~0u)
437 throw Exception("No suitable queue family available.");
438 queueSet.insert(queueFamilyIndex[i]);
439 }
440
441 delete []pqueueFamilyProps;
442
443 //queue creation
444 VkDeviceQueueCreateInfo queueCreateInfo[QUEUE_INDEX_COUNT];
445 uint queueCount = 0;
446 for(uint queueFamilyIndex1 : queueSet){
447 //logical device
448 static const float queuePriorities[] = {1.0f};
449 queueCreateInfo[queueCount] = (VkDeviceQueueCreateInfo){};
450 queueCreateInfo[queueCount].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
451 queueCreateInfo[queueCount].queueFamilyIndex = queueFamilyIndex1;
452 queueCreateInfo[queueCount].queueCount = 1;
453 queueCreateInfo[queueCount].pQueuePriorities = queuePriorities;
454 ++queueCount;
455 }
456
457 VkPhysicalDeviceFeatures physicalDevFeatures = {};
458 physicalDevFeatures.geometryShader = VK_TRUE;
459 //physicalDevFeatures.multiViewport = VK_TRUE;
460
461 uint devExtCount;
462 vkEnumerateDeviceExtensionProperties(physicalDev,0,&devExtCount,0);
463 VkExtensionProperties *pdevExtProps = new VkExtensionProperties[devExtCount];
464 vkEnumerateDeviceExtensionProperties(physicalDev,0,&devExtCount,pdevExtProps);
465
466 //device extensions
467 const char *pdevExtensions[] = {
468 VK_KHR_SWAPCHAIN_EXTENSION_NAME,
469 VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
470 //VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
471 VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
472 VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,
473 VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
474 VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME
475 //VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
476 //VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
477 //VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
478 //VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
479 //VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME
480 //VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME,VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME};
481 };
482
483 DebugPrintf(stdout,"Enumerating required device extensions\n");
484 uint devExtFound = 0;
485 for(uint i = 0; i < devExtCount; ++i)
486 for(uint j = 0; j < sizeof(pdevExtensions)/sizeof(pdevExtensions[0]); ++j)
487 if(strcmp(pdevExtProps[i].extensionName,pdevExtensions[j]) == 0){
488 printf(" %s\n",pdevExtensions[j]);
489 ++devExtFound;
490 }
491 if(devExtFound < sizeof(pdevExtensions)/sizeof(pdevExtensions[0]))
492 throw Exception("Could not find all required device extensions.");
493
494 VkDeviceCreateInfo devCreateInfo = {};
495 devCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
496 devCreateInfo.pQueueCreateInfos = queueCreateInfo;
497 devCreateInfo.queueCreateInfoCount = queueCount;
498 devCreateInfo.pEnabledFeatures = &physicalDevFeatures;
499 devCreateInfo.ppEnabledExtensionNames = pdevExtensions;
500 devCreateInfo.enabledExtensionCount = sizeof(pdevExtensions)/sizeof(pdevExtensions[0]);
501 if(debugLayers){
502 devCreateInfo.ppEnabledLayerNames = players;
503 devCreateInfo.enabledLayerCount = sizeof(players)/sizeof(players[0]);
504 }else{
505 devCreateInfo.ppEnabledLayerNames = 0;
506 devCreateInfo.enabledLayerCount = 0;
507 }
508 if(vkCreateDevice(physicalDev,&devCreateInfo,0,&logicalDev) != VK_SUCCESS)
509 throw Exception("Failed to create a logical device.");
510
511 delete []pdevExtProps;
512
513 for(uint i = 0; i < QUEUE_INDEX_COUNT; ++i)
514 vkGetDeviceQueue(logicalDev,queueFamilyIndex[i],0,&queue[i]);
515
516 //render pass (later an array of these for different purposes)
517 VkAttachmentReference attachmentRef = {};
518 attachmentRef.attachment = 0;
519 attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
520
521 VkSubpassDescription subpassDesc = {};
522 subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
523 subpassDesc.colorAttachmentCount = 1;
524 subpassDesc.pColorAttachments = &attachmentRef;
525
526 VkAttachmentDescription attachmentDesc = {};
527 attachmentDesc.format = VK_FORMAT_B8G8R8A8_UNORM;
528 attachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;
529 attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;//VK_ATTACHMENT_LOAD_OP_CLEAR;
530 attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
531 attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
532 attachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
533 attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
534 attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
535
536 VkSubpassDependency subpassDependency = {};
537 subpassDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
538 subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
539 subpassDependency.srcAccessMask = 0;
540 subpassDependency.dstSubpass = 0;
541 subpassDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
542 subpassDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
543 //subpassDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|VK_ACCESS_MEMORY_READ_BIT;
544
545 VkRenderPassCreateInfo renderPassCreateInfo = {};
546 renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
547 renderPassCreateInfo.attachmentCount = 1;
548 renderPassCreateInfo.pAttachments = &attachmentDesc;
549 renderPassCreateInfo.subpassCount = 1;
550 renderPassCreateInfo.pSubpasses = &subpassDesc;
551 renderPassCreateInfo.dependencyCount = 1;
552 renderPassCreateInfo.pDependencies = &subpassDependency;
553 if(vkCreateRenderPass(logicalDev,&renderPassCreateInfo,0,&renderPass) != VK_SUCCESS)
554 throw Exception("Failed to create a render pass.");
555
556 InitializeSwapchain();
557
558 //sampler
559 VkSamplerCreateInfo samplerCreateInfo = {};
560 samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
561 samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
562 samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
563 samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
564 samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
565 samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
566 samplerCreateInfo.anisotropyEnable = VK_FALSE;
567 samplerCreateInfo.maxAnisotropy = 1;
568 samplerCreateInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
569 samplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
570 samplerCreateInfo.compareEnable = VK_FALSE;
571 samplerCreateInfo.compareOp = VK_COMPARE_OP_ALWAYS;
572 samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
573 samplerCreateInfo.mipLodBias = 0.0f;
574 samplerCreateInfo.minLod = 0.0f;
575 samplerCreateInfo.maxLod = 0.0f;
576 if(vkCreateSampler(logicalDev,&samplerCreateInfo,0,&pointSampler) != VK_SUCCESS)
577 throw Exception("Failed to create a sampler.");
578
579 //descriptor pool
580 //descriptors of this pool
581 /*VkDescriptorPoolSize descPoolSizes[2];
582 descPoolSizes[0] = (VkDescriptorPoolSize){};
583 descPoolSizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLER;//VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
584 descPoolSizes[0].descriptorCount = 16;
585
586 descPoolSizes[1] = (VkDescriptorPoolSize){};
587 descPoolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
588 descPoolSizes[1].descriptorCount = 16;
589
590 VkDescriptorPoolCreateInfo descPoolCreateInfo = {};
591 descPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
592 descPoolCreateInfo.poolSizeCount = sizeof(descPoolSizes)/sizeof(descPoolSizes[0]);
593 descPoolCreateInfo.pPoolSizes = descPoolSizes;
594 descPoolCreateInfo.maxSets = 16;
595 descPoolCreateInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
596 if(vkCreateDescriptorPool(logicalDev,&descPoolCreateInfo,0,&descPool) != VK_SUCCESS)
597 throw Exception("Failed to create a descriptor pool.");*/
598
599 //command pool and buffers
600 VkCommandPoolCreateInfo commandPoolCreateInfo = {};
601 commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
602 commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex[QUEUE_INDEX_GRAPHICS];
603 commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
604 if(vkCreateCommandPool(logicalDev,&commandPoolCreateInfo,0,&commandPool) != VK_SUCCESS)
605 throw Exception("Failed to create a command pool.");
606
607 pcommandBuffers = new VkCommandBuffer[swapChainImageCount];
608 pcopyCommandBuffers = new VkCommandBuffer[swapChainImageCount];
609
610 VkCommandBufferAllocateInfo commandBufferAllocateInfo = {};
611 commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
612 commandBufferAllocateInfo.commandPool = commandPool;
613 commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
614 commandBufferAllocateInfo.commandBufferCount = swapChainImageCount;
615 if(vkAllocateCommandBuffers(logicalDev,&commandBufferAllocateInfo,pcommandBuffers) != VK_SUCCESS)
616 throw Exception("Failed to allocate command buffers.");
617
618 if(vkAllocateCommandBuffers(logicalDev,&commandBufferAllocateInfo,pcopyCommandBuffers) != VK_SUCCESS)
619 throw Exception("Failed to allocate copy command buffer.");
620
621 shaders.reserve(1024);
622 pipelines.reserve(1024);
623 updateQueue.reserve(1024);
624 titleUpdateQueue.reserve(1024);
625 scissorRegions.reserve(32);
626 presentRectLayers.reserve(32);
627
628 ptextEngine = new TextEngine(pfontName,fontSize,this);
629 }
630
InitializeSwapchain()631 void CompositorInterface::InitializeSwapchain(){
632 imageExtent = GetExtent();
633
634 VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
635 swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
636 swapchainCreateInfo.surface = surface;
637 swapchainCreateInfo.minImageCount = std::max(surfaceCapabilities.minImageCount,3u);
638 swapchainCreateInfo.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
639 swapchainCreateInfo.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
640 swapchainCreateInfo.imageExtent = imageExtent;
641 swapchainCreateInfo.imageArrayLayers = 1;
642 swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
643 if(queueFamilyIndex[QUEUE_INDEX_GRAPHICS] != queueFamilyIndex[QUEUE_INDEX_PRESENT]){
644 DebugPrintf(stdout,"concurrent swap chain\n");
645 static const uint queueFamilyIndex1[] = {queueFamilyIndex[QUEUE_INDEX_GRAPHICS],queueFamilyIndex[QUEUE_INDEX_PRESENT]};
646 swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
647 swapchainCreateInfo.queueFamilyIndexCount = 2;
648 swapchainCreateInfo.pQueueFamilyIndices = queueFamilyIndex1;
649 }else swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
650 swapchainCreateInfo.preTransform = surfaceCapabilities.currentTransform;
651 swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
652 //swapchainCreateInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
653 swapchainCreateInfo.presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
654 swapchainCreateInfo.clipped = VK_TRUE;
655 swapchainCreateInfo.oldSwapchain = 0;
656 if(vkCreateSwapchainKHR(logicalDev,&swapchainCreateInfo,0,&swapChain) != VK_SUCCESS)
657 throw Exception("Failed to create swap chain.");
658
659 DebugPrintf(stdout,"Swap chain image extent %ux%u\n",swapchainCreateInfo.imageExtent.width,swapchainCreateInfo.imageExtent.height);
660 vkGetSwapchainImagesKHR(logicalDev,swapChain,&swapChainImageCount,0);
661 pswapChainImages = new VkImage[swapChainImageCount];
662 vkGetSwapchainImagesKHR(logicalDev,swapChain,&swapChainImageCount,pswapChainImages);
663
664 VkImageViewCreateInfo imageViewCreateInfo = {};
665 imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
666 imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
667 imageViewCreateInfo.format = VK_FORMAT_B8G8R8A8_UNORM;
668 imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
669 imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
670 imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
671 imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
672 imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
673 imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
674 imageViewCreateInfo.subresourceRange.levelCount = 1;
675 imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
676 imageViewCreateInfo.subresourceRange.layerCount = 1;
677 pswapChainImageViews = new VkImageView[swapChainImageCount];
678 pframebuffers = new VkFramebuffer[swapChainImageCount];
679 for(uint i = 0; i < swapChainImageCount; ++i){
680 imageViewCreateInfo.image = pswapChainImages[i];
681 if(vkCreateImageView(logicalDev,&imageViewCreateInfo,0,&pswapChainImageViews[i]) != VK_SUCCESS)
682 throw Exception("Failed to create a swap chain image view.");
683
684 VkFramebufferCreateInfo framebufferCreateInfo = {};
685 framebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
686 framebufferCreateInfo.renderPass = renderPass;
687 framebufferCreateInfo.attachmentCount = 1;
688 framebufferCreateInfo.pAttachments = &pswapChainImageViews[i];
689 framebufferCreateInfo.width = imageExtent.width;
690 framebufferCreateInfo.height = imageExtent.height;
691 framebufferCreateInfo.layers = 1;
692 if(vkCreateFramebuffer(logicalDev,&framebufferCreateInfo,0,&pframebuffers[i]) != VK_SUCCESS)
693 throw Exception("Failed to create a framebuffer.");
694 }
695
696 VkSemaphoreCreateInfo semaphoreCreateInfo = {};
697 semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
698
699 VkFenceCreateInfo fenceCreateInfo = {};
700 fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
701 fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
702
703 psemaphore = new VkSemaphore[swapChainImageCount][SEMAPHORE_INDEX_COUNT];
704 pfence = new VkFence[swapChainImageCount];
705
706 for(uint i = 0; i < swapChainImageCount; ++i){
707 if(vkCreateFence(logicalDev,&fenceCreateInfo,0,&pfence[i]) != VK_SUCCESS)
708 throw Exception("Failed to create a fence.");
709 for(uint j = 0; j < SEMAPHORE_INDEX_COUNT; ++j)
710 if(vkCreateSemaphore(logicalDev,&semaphoreCreateInfo,0,&psemaphore[i][j]) != VK_SUCCESS)
711 throw Exception("Failed to create a semaphore.");
712 }
713 }
714
DestroyRenderEngine()715 void CompositorInterface::DestroyRenderEngine(){
716 DebugPrintf(stdout,"Compositor cleanup\n");
717
718 delete ptextEngine;
719
720 for(TextureCacheEntry &textureCacheEntry : textureCache)
721 delete textureCacheEntry.ptexture;
722
723 for(auto m : pipelines)
724 delete m.second;
725 shaders.clear();
726
727 vkFreeCommandBuffers(logicalDev,commandPool,swapChainImageCount,pcommandBuffers);
728 vkFreeCommandBuffers(logicalDev,commandPool,swapChainImageCount,pcopyCommandBuffers);
729 delete []pcommandBuffers;
730 delete []pcopyCommandBuffers;
731 vkDestroyCommandPool(logicalDev,commandPool,0);
732
733 for(VkDescriptorPool &descPool : descPoolArray)
734 vkDestroyDescriptorPool(logicalDev,descPool,0);
735 descPoolArray.clear();
736
737 vkDestroySampler(logicalDev,pointSampler,0);
738
739 DestroySwapchain();
740
741 vkDestroyRenderPass(logicalDev,renderPass,0);
742
743 vkDestroyDevice(logicalDev,0);
744
745 ((PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance,"vkDestroyDebugReportCallbackEXT"))(instance,debugReportCb,0);
746
747 vkDestroySurfaceKHR(instance,surface,0);
748 vkDestroyInstance(instance,0);
749 }
750
DestroySwapchain()751 void CompositorInterface::DestroySwapchain(){
752 for(uint i = 0; i < swapChainImageCount; ++i){
753 vkDestroyFence(logicalDev,pfence[i],0);
754 for(uint j = 0; j < SEMAPHORE_INDEX_COUNT; ++j)
755 vkDestroySemaphore(logicalDev,psemaphore[i][j],0);
756
757 vkDestroyFramebuffer(logicalDev,pframebuffers[i],0);
758 vkDestroyImageView(logicalDev,pswapChainImageViews[i],0);
759 }
760 delete []psemaphore;
761 delete []pfence;
762 delete []pswapChainImageViews;
763 delete []pswapChainImages;
764 vkDestroySwapchainKHR(logicalDev,swapChain,0);
765 }
766
AddShader(const char * pname,const Blob * pblob)767 void CompositorInterface::AddShader(const char *pname, const Blob *pblob){
768 shaders.emplace_back(pname,pblob,this);
769 }
770
AddDamageRegion(const VkRect2D * prect)771 void CompositorInterface::AddDamageRegion(const VkRect2D *prect){
772 if(!scissoring)
773 return;
774 //find the regions that are completely covered by the param and replace them all with the one larger area
775 scissorRegions.erase(std::remove_if(scissorRegions.begin(),scissorRegions.end(),[&](auto &scissorRegion)->bool{
776 return prect->offset.x <= scissorRegion.first.offset.x && prect->offset.y <= scissorRegion.first.offset.y
777 && prect->offset.x+prect->extent.width >= scissorRegion.first.offset.x+scissorRegion.first.extent.width
778 && prect->offset.y+prect->extent.height >= scissorRegion.first.offset.y+scissorRegion.first.extent.height;
779 }),scissorRegions.end());
780 scissorRegions.push_back(std::pair<VkRect2D, uint>(*prect,0));
781
782 VkRectLayerKHR &rectLayer = presentRectLayers.emplace_back();
783 rectLayer.offset = {std::max(prect->offset.x,0),std::max(prect->offset.y,0)};
784 rectLayer.extent = {
785 prect->extent.width+std::min((int)imageExtent.width-(rectLayer.offset.x+(int)prect->extent.width),0),
786 prect->extent.height+std::min((int)imageExtent.height-(rectLayer.offset.y+(int)prect->extent.height),0)
787 };
788 rectLayer.layer = 0;
789 }
790
AddDamageRegion(const WManager::Client * pclient)791 void CompositorInterface::AddDamageRegion(const WManager::Client *pclient){
792 if(!scissoring)
793 return;
794 glm::ivec2 margin = 4*glm::ivec2(
795 pclient->pcontainer->margin.x*(float)imageExtent.width,
796 pclient->pcontainer->margin.y*(float)imageExtent.width); //due to aspect, this must be *width
797
798 glm::ivec2 titlePad = glm::ivec2(
799 pclient->pcontainer->titlePad.x*(float)imageExtent.width,
800 pclient->pcontainer->titlePad.y*(float)imageExtent.width);
801 glm::ivec2 titlePadOffset = glm::min(titlePad,glm::ivec2(0));
802 glm::ivec2 titlePadExtent = glm::max(titlePad,glm::ivec2(0));
803
804 VkRect2D rect1;
805 rect1.offset = {pclient->rect.x-margin.x+titlePadOffset.x,pclient->rect.y-margin.y+titlePadOffset.y};
806 rect1.extent = {pclient->rect.w+2*margin.x-titlePadOffset.x+titlePadExtent.x,pclient->rect.h+2*margin.y-titlePadOffset.y+titlePadExtent.y};
807 AddDamageRegion(&rect1);
808 rect1.offset = {pclient->oldRect.x-margin.x+titlePadOffset.x,pclient->oldRect.y-margin.y+titlePadOffset.y};
809 rect1.extent = {pclient->oldRect.w+2*margin.x-titlePadOffset.x+titlePadExtent.x,pclient->oldRect.h+2*margin.y-titlePadOffset.y+titlePadExtent.y};
810 AddDamageRegion(&rect1);
811 }
812
WaitIdle()813 void CompositorInterface::WaitIdle(){
814 vkDeviceWaitIdle(logicalDev);
815 }
816
CreateRenderQueueAppendix(const WManager::Client * pclient,const WManager::Container * pfocus)817 void CompositorInterface::CreateRenderQueueAppendix(const WManager::Client *pclient, const WManager::Container *pfocus){
818 auto s = [&](auto &p)->bool{
819 return pclient == std::get<0>(p);
820 };
821 for(auto m = std::find_if(appendixQueue.begin(),appendixQueue.end(),s);
822 m != appendixQueue.end(); m = std::find_if(m,appendixQueue.end(),s)){
823 RenderObject renderObject;
824 renderObject.pclient = std::get<1>(*m);
825 renderObject.pclientFrame = std::get<2>(*m);
826 renderObject.pclientFrame->oldShaderFlags = renderObject.pclientFrame->shaderFlags;
827 renderObject.pclientFrame->shaderFlags =
828 (renderObject.pclient->pcontainer == pfocus?ClientFrame::SHADER_FLAG_FOCUS:0)
829 |(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FLOATING?ClientFrame::SHADER_FLAG_FLOATING:0)
830 //|(renderObject.pclient->pcontainer->pParent && renderObject.pclient->pParent->flags & WManager::Container::FLAG_STACKED?ClientFrame::SHADER_FLAG_STACKED:0)
831 |renderObject.pclientFrame->shaderUserFlags;
832 renderQueue.push_back(renderObject);
833
834 CreateRenderQueueAppendix(std::get<1>(*m),pfocus);
835
836 m = appendixQueue.erase(m);
837 }
838 }
839
CreateRenderQueue(const WManager::Container * pcontainer,const WManager::Container * pfocus)840 void CompositorInterface::CreateRenderQueue(const WManager::Container *pcontainer, const WManager::Container *pfocus){
841 if(!pcontainer->pch)
842 return; //workaround a bug with stackQueue, need to fix this properly
843 for(const WManager::Container *pcont : pcontainer->stackQueue){
844 if(pcont->pclient){
845 ClientFrame *pclientFrame = dynamic_cast<ClientFrame *>(pcont->pclient);
846 if(!pclientFrame || (!pclientFrame->enabled && pclientFrame != pfsApp))
847 continue;
848
849 RenderObject renderObject;
850 renderObject.pclient = pcont->pclient;
851 renderObject.pclientFrame = pclientFrame;
852 renderObject.pclientFrame->oldShaderFlags = renderObject.pclientFrame->shaderFlags;
853 renderObject.pclientFrame->shaderFlags =
854 (pcont == pfocus || pcontainer == pfocus?ClientFrame::ClientFrame::SHADER_FLAG_FOCUS:0)
855 //|(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FLOATING?ClientFrame::SHADER_FLAG_FLOATING:0) //probably not required here
856 |(renderObject.pclient->pcontainer->pParent && renderObject.pclient->pcontainer->pParent->flags & WManager::Container::FLAG_STACKED?ClientFrame::SHADER_FLAG_STACKED:0)
857 |renderObject.pclientFrame->shaderUserFlags;
858 renderQueue.push_back(renderObject);
859 }
860 CreateRenderQueue(pcont,pcontainer == pfocus?pcont:pfocus);
861 }
862
863 if(!pcontainer->pclient)
864 return;
865 CreateRenderQueueAppendix(pcontainer->pclient,pfocus);
866 }
867
PollFrameFence(bool suspend)868 bool CompositorInterface::PollFrameFence(bool suspend){
869 if(suspend != suspended && !unredirected){
870 if(suspend)
871 Suspend();
872 else Resume();
873 }
874 if(unredirOnFullscreen){
875 if(pfsApp && !unredirected){
876 DebugPrintf(stdout,"unredirect %p\n",pfsApp);
877 pfsApp->Exclude(true);
878 pfsAppPrev = pfsApp;
879 unredirected = true;
880 Suspend();
881 }else
882 if(!pfsApp && unredirected){
883 DebugPrintf(stdout,"redirect %p\n",pfsAppPrev);
884 if(pfsAppPrev){ //may have been closed before leaving fullscreen
885 pfsAppPrev->Exclude(false);
886 pfsAppPrev = 0;
887 }
888 unredirected = false;
889 Resume();
890 }
891 }
892
893 if(suspended && !unredirected)
894 return false;
895
896 frameApproval = false;
897 if(unredirected)
898 return true; //let the program proceed to GenerateCommandBuffers (without frameApproval), where the redirection state will be evaluated
899
900 for(uint i = 0; i < 3; ++i){
901 if(vkAcquireNextImageKHR(logicalDev,swapChain,std::numeric_limits<uint64_t>::max(),psemaphore[currentFrame][SEMAPHORE_INDEX_IMAGE_AVAILABLE],0,&imageIndex) != VK_SUCCESS){
902 DebugPrintf(stderr,"Failed to acquire a swap chain image. Attempting to recreate (%u/3)...\n",i+1);
903 WaitIdle();
904 DestroySwapchain();
905 InitializeSwapchain();
906 continue;
907 }
908 break;
909 }
910
911 if(vkWaitForFences(logicalDev,1,&pfence[currentFrame],VK_TRUE,0) == VK_TIMEOUT)
912 return false;
913 vkResetFences(logicalDev,1,&pfence[currentFrame]);
914
915 //release the textures no longer in use
916 textureCache.erase(std::remove_if(textureCache.begin(),textureCache.end(),[&](auto &textureCacheEntry)->bool{
917 if(frameTag < textureCacheEntry.releaseTag+swapChainImageCount+1 || timespec_diff(frameTime,textureCacheEntry.releaseTime) < 5.0f)
918 return false;
919 delete textureCacheEntry.ptexture;
920 return true;
921 }),textureCache.end());
922
923 descSetCache.erase(std::remove_if(descSetCache.begin(),descSetCache.end(),[&](auto &descSetCacheEntry)->bool{
924 if(frameTag < descSetCacheEntry.releaseTag+swapChainImageCount+1)
925 return false;
926 auto m = std::find_if(descPoolReference.begin(),descPoolReference.end(),[&](auto &p)->bool{
927 return descSetCacheEntry.pdescSets == p.first;
928 });
929 if(m == descPoolReference.end())
930 return true;
931 vkFreeDescriptorSets(logicalDev,(*m).second,descSetCacheEntry.setCount,descSetCacheEntry.pdescSets);
932 descPoolReference.erase(m);
933 printf("************ releasing desc set\n");
934
935 delete []descSetCacheEntry.pdescSets;
936 return true;
937 }),descSetCache.end());
938
939 ptextEngine->ReleaseCycle();
940
941 frameApproval = true;
942 return true;
943 }
944
GenerateCommandBuffers(const WManager::Container * proot,const std::vector<std::pair<const WManager::Client *,WManager::Client * >> * pstackAppendix,const WManager::Container * pfocus)945 void CompositorInterface::GenerateCommandBuffers(const WManager::Container *proot, const std::vector<std::pair<const WManager::Client *, WManager::Client *>> *pstackAppendix, const WManager::Container *pfocus){
946 if(!proot)
947 return;
948
949 //Create a render list elements arranged from back to front
950 renderQueue.clear();
951 appendixQueue.clear();
952 for(auto &p : *pstackAppendix){
953 ClientFrame *pclientFrame = dynamic_cast<ClientFrame *>(p.second);
954 if(!pclientFrame || !pclientFrame->enabled)
955 continue;
956 if(p.first){
957 appendixQueue.push_back(AppendixQueueElement(p.first,p.second,pclientFrame));
958 continue;
959 }
960 //desktop features are placed first
961 RenderObject renderObject;
962 renderObject.pclient = p.second;
963 renderObject.pclientFrame = pclientFrame;
964 renderObject.pclientFrame->oldShaderFlags = renderObject.pclientFrame->shaderFlags;
965 renderObject.pclientFrame->shaderFlags =
966 (renderObject.pclient->pcontainer == pfocus?ClientFrame::SHADER_FLAG_FOCUS:0)
967 |(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FLOATING?ClientFrame::SHADER_FLAG_FLOATING:0)
968 |(renderObject.pclient->pcontainer->pParent && renderObject.pclient->pcontainer->pParent->flags & WManager::Container::FLAG_STACKED?ClientFrame::SHADER_FLAG_STACKED:0)
969 |renderObject.pclientFrame->shaderUserFlags;
970 renderQueue.push_back(renderObject);
971 }
972
973 CreateRenderQueue(proot,pfocus);
974
975 for(auto m = appendixQueue.begin(); m != appendixQueue.end();){
976 auto k = std::find_if(appendixQueue.begin(),appendixQueue.end(),[&](auto &p)->bool{
977 return std::get<0>(*m) == std::get<1>(p);
978 });
979 if(k != appendixQueue.end()){
980 ++m;
981 continue;
982 }
983
984 RenderObject renderObject;
985 renderObject.pclient = std::get<1>(*m);
986 renderObject.pclientFrame = std::get<2>(*m);
987 renderObject.pclientFrame->oldShaderFlags = renderObject.pclientFrame->shaderFlags;
988 renderObject.pclientFrame->shaderFlags =
989 (renderObject.pclient->pcontainer == pfocus?ClientFrame::SHADER_FLAG_FOCUS:0)
990 |(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FLOATING?ClientFrame::SHADER_FLAG_FLOATING:0)
991 |(renderObject.pclient->pcontainer->pParent && renderObject.pclient->pcontainer->pParent->flags & WManager::Container::FLAG_STACKED?ClientFrame::SHADER_FLAG_STACKED:0)
992 |renderObject.pclientFrame->shaderUserFlags;
993 renderQueue.push_back(renderObject);
994
995 CreateRenderQueueAppendix(std::get<1>(*m),pfocus);
996
997 m = appendixQueue.erase(m);
998 }
999
1000 for(auto &p : appendixQueue){ //push the remaining (untransient) windows to the end of the queue
1001 RenderObject renderObject;
1002 renderObject.pclient = std::get<1>(p);
1003 renderObject.pclientFrame = std::get<2>(p);
1004 renderObject.pclientFrame->oldShaderFlags = renderObject.pclientFrame->shaderFlags;
1005 renderObject.pclientFrame->shaderFlags =
1006 (renderObject.pclient->pcontainer == pfocus?ClientFrame::SHADER_FLAG_FOCUS:0)
1007 |(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FLOATING?ClientFrame::SHADER_FLAG_FLOATING:0)
1008 |(renderObject.pclient->pcontainer->pParent && renderObject.pclient->pcontainer->pParent->flags & WManager::Container::FLAG_STACKED?ClientFrame::SHADER_FLAG_STACKED:0)
1009 |renderObject.pclientFrame->shaderUserFlags;
1010 renderQueue.push_back(renderObject);
1011 }
1012
1013 pfsApp = 0;
1014
1015 playingAnimation = false;
1016 clock_gettime(CLOCK_MONOTONIC,&frameTime);
1017
1018 for(uint i = 0; i < renderQueue.size(); ++i){
1019 RenderObject &renderObject = renderQueue[i];
1020
1021 float s;
1022 if(enableAnimation){
1023 float t = timespec_diff(frameTime,renderObject.pclient->translationTime);
1024 s = std::clamp(t/animationDuration,0.0f,1.0f);
1025 s = 1.0f/(1.0f+expf(-10.0f*s+5.0f));
1026 }else s = 1.0f;
1027
1028 glm::vec2 oldRect1 = glm::vec2(renderObject.pclient->oldRect.x,renderObject.pclient->oldRect.y);
1029 renderObject.pclient->position = oldRect1+s*(glm::vec2(renderObject.pclient->rect.x,renderObject.pclient->rect.y)-oldRect1);
1030 if(s < 0.99f
1031 && (renderObject.pclient->oldRect.x != renderObject.pclient->rect.x || renderObject.pclient->oldRect.y != renderObject.pclient->rect.y)
1032 && !(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FLOATING)){
1033 AddDamageRegion(renderObject.pclient); //need to keep adding the client for as long as the animation is playing
1034
1035 playingAnimation = true;
1036 renderObject.pclientFrame->animationCompleted = false;
1037
1038 }else
1039 if(!renderObject.pclientFrame->animationCompleted){
1040 AddDamageRegion(renderObject.pclient);
1041 renderObject.pclientFrame->animationCompleted = true;
1042
1043 renderObject.pclient->position = glm::vec2(renderObject.pclient->rect.x,renderObject.pclient->rect.y);
1044
1045 }else{
1046 renderObject.pclient->position = glm::vec2(renderObject.pclient->rect.x,renderObject.pclient->rect.y);
1047
1048 if(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FULLSCREEN)
1049 pfsApp = renderObject.pclientFrame;
1050 }
1051
1052 if(renderObject.pclientFrame->shaderFlags != renderObject.pclientFrame->oldShaderFlags)
1053 AddDamageRegion(renderObject.pclient);
1054 }
1055
1056 if(unredirected || !frameApproval)
1057 return;
1058
1059 VkCommandBufferBeginInfo commandBufferBeginInfo = {};
1060 commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1061 commandBufferBeginInfo.flags = 0;
1062 if(vkBeginCommandBuffer(pcopyCommandBuffers[currentFrame],&commandBufferBeginInfo) != VK_SUCCESS)
1063 throw Exception("Failed to begin command buffer recording.");
1064
1065 ClientFrame *pbackground1 = dynamic_cast<ClientFrame *>(pbackground);
1066 if(pbackground1)
1067 pbackground1->UpdateContents(&pcopyCommandBuffers[currentFrame]);
1068
1069 //TODO: update only visible clients
1070 for(ClientFrame *pclientFrame : updateQueue)
1071 pclientFrame->UpdateContents(&pcopyCommandBuffers[currentFrame]);
1072 updateQueue.clear();
1073
1074 for(ClientFrame *pclientFrame : titleUpdateQueue)
1075 pclientFrame->ptitle->Set(pclientFrame->title.c_str(),&pcopyCommandBuffers[currentFrame]);
1076 titleUpdateQueue.clear();
1077
1078 if(vkEndCommandBuffer(pcopyCommandBuffers[currentFrame]) != VK_SUCCESS)
1079 throw Exception("Failed to end command buffer recording.");
1080
1081 commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
1082 if(vkBeginCommandBuffer(pcommandBuffers[currentFrame],&commandBufferBeginInfo) != VK_SUCCESS)
1083 throw Exception("Failed to begin command buffer recording.");
1084
1085 //TODO: debug option: draw frames around scissor area
1086 VkRect2D scissor;
1087 if(scissoring){
1088 glm::ivec2 a = glm::ivec2(imageExtent.width,imageExtent.height);
1089 glm::ivec2 b = glm::ivec2(0);
1090 for(auto m = scissorRegions.begin(); m != scissorRegions.end();){
1091 if(((*m).second & 1<<imageIndex) == 0){
1092 glm::ivec2 a1 = glm::ivec2((*m).first.offset.x,(*m).first.offset.y);
1093 glm::ivec2 b1 = a1+glm::ivec2((*m).first.extent.width,(*m).first.extent.height);
1094 a = glm::min(a,a1);
1095 b = glm::max(b,b1);
1096
1097 (*m).second |= 1<<imageIndex;
1098 }
1099
1100 //As soon as the rectangle has been drawn for every image of the swap chain, remove it
1101 if(~(~0u<<swapChainImageCount) == (*m).second)
1102 m = scissorRegions.erase(m);
1103 else ++m;
1104 }
1105
1106 scissor.offset = {std::max(a.x,0),std::max(a.y,0)};
1107 scissor.extent = {std::max(b.x-scissor.offset.x,0),std::max(b.y-scissor.offset.y,0)};
1108 vkCmdSetScissor(pcommandBuffers[currentFrame],0,1,&scissor);
1109 }
1110
1111 //static const VkClearValue clearValue = {1.0f,1.0f,1.0f,1.0f};
1112 VkRenderPassBeginInfo renderPassBeginInfo = {};
1113 renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
1114 renderPassBeginInfo.renderPass = renderPass;
1115 renderPassBeginInfo.framebuffer = pframebuffers[imageIndex];
1116 renderPassBeginInfo.renderArea.offset = {0,0};
1117 renderPassBeginInfo.renderArea.extent = imageExtent;
1118 renderPassBeginInfo.clearValueCount = 0;//1;
1119 renderPassBeginInfo.pClearValues = 0;//&clearValue;
1120 vkCmdBeginRenderPass(pcommandBuffers[currentFrame],&renderPassBeginInfo,VK_SUBPASS_CONTENTS_INLINE);
1121
1122 //clear manually since some parts of the buffer we want to retain based on damage
1123 if(pbackground){
1124 vkCmdBindPipeline(pcommandBuffers[currentFrame],VK_PIPELINE_BIND_POINT_GRAPHICS,pbackground->passignedSet->p->pipeline);
1125
1126 VkRect2D screenRect;
1127 screenRect.offset = {0,0};
1128 screenRect.extent = imageExtent;
1129 pbackground->Draw(screenRect,glm::vec2(0.0f),glm::vec2(0.0f),glm::vec2(0.0f),0,0,&pcommandBuffers[currentFrame]);
1130 }
1131
1132 //TODO: stencil buffer optimization
1133
1134 //for(RenderObject &renderObject : renderQueue){
1135 for(uint i = 0; i < renderQueue.size(); ++i){
1136 RenderObject &renderObject = renderQueue[i];
1137
1138 if((sint)renderObject.pclient->position.x+renderObject.pclient->rect.w <= 1 || (sint)renderObject.pclient->position.y+renderObject.pclient->rect.h <= 1
1139 || (sint)renderObject.pclient->position.x > (sint)imageExtent.width || (sint)renderObject.pclient->position.y > (sint)imageExtent.height)
1140 continue;
1141
1142 VkRect2D frame;
1143 frame.offset = {(sint)renderObject.pclient->position.x,(sint)renderObject.pclient->position.y};
1144 frame.extent = {renderObject.pclient->rect.w,renderObject.pclient->rect.h};
1145 //frame.offset = {renderObject.pclient->rect.x,renderObject.pclient->rect.y};
1146 //frame.extent = {renderObject.pclient->rect.w,renderObject.pclient->rect.h};
1147
1148 /*VkRect2D scissor = frame;
1149 for(uint j = i+1; j < renderQueue.size(); ++j){
1150 RenderObject &renderObject1 = renderQueue[j];
1151
1152 if(frame.offset.y >= renderObject1.pclient->rect.y-1 &&
1153 frame.offset.y+frame.extent.height <= renderObject1.pclient->rect.y+renderObject1.pclient->rect.h+1){
1154 if(scissor.offset.x+scissor.extent.width > renderObject1.pclient->rect.x &&
1155 scissor.offset.x < renderObject1.pclient->rect.x)
1156 scissor.extent.width = renderObject1.pclient->rect.x-scissor.offset.x;
1157
1158 if(renderObject1.pclient->rect.x+renderObject1.pclient->rect.w > scissor.offset.x &&
1159 renderObject1.pclient->rect.x < scissor.offset.x){
1160 sint oldOffset = scissor.offset.x;
1161 scissor.offset.x = renderObject1.pclient->rect.x+renderObject1.pclient->rect.w;
1162 scissor.extent.width -= scissor.offset.x-oldOffset;
1163 }
1164 }
1165 }*/
1166
1167 vkCmdBindPipeline(pcommandBuffers[currentFrame],VK_PIPELINE_BIND_POINT_GRAPHICS,renderObject.pclientFrame->passignedSet->p->pipeline);
1168
1169 renderObject.pclientFrame->Draw(frame,renderObject.pclient->pcontainer->margin,renderObject.pclient->pcontainer->titlePad,renderObject.pclient->pcontainer->titleSpan,renderObject.pclient->stackIndex,renderObject.pclientFrame->shaderFlags,&pcommandBuffers[currentFrame]);
1170
1171 if(renderObject.pclient->pcontainer->titleBar != WManager::Container::TITLEBAR_NONE && !(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FULLSCREEN) && renderObject.pclientFrame->ptitle){
1172 glm::uvec2 titlePosition = glm::uvec2(frame.offset.x,frame.offset.y);
1173 if(renderObject.pclient->titlePad1.x > 1e-5)
1174 titlePosition.x += frame.extent.width;
1175 if(renderObject.pclient->titlePad1.y > 1e-5)
1176 titlePosition.y += frame.extent.height;
1177 glm::vec2 titlePadAbs = glm::abs(renderObject.pclient->titlePad1);
1178 if(titlePadAbs.x > titlePadAbs.y){
1179 titlePosition.y += renderObject.pclient->titleStackOffset.y+renderObject.pclientFrame->ptitle->GetTextLength()-(renderObject.pclientFrame->ptitle->GetTextLength()-renderObject.pclient->titleFrameExtent.y);
1180 titlePosition.x += (ptextEngine->fontFace->glyph->metrics.horiBearingY>>6)/2;
1181 }else{
1182 titlePosition.x += renderObject.pclient->titleStackOffset.x;
1183 titlePosition.y += (ptextEngine->fontFace->glyph->metrics.horiBearingY>>6)/2;
1184 }
1185 titlePosition += 0.5f*renderObject.pclient->titlePad1;
1186
1187 //intersect the title region with scissor rectangle
1188 glm::ivec2 titleRectOffset = glm::ivec2(renderObject.pclient->titleRect.x,renderObject.pclient->titleRect.y);
1189 glm::ivec2 scissorOffset = glm::ivec2(scissor.offset.x,scissor.offset.y);
1190 glm::ivec2 offset = glm::max(titleRectOffset,scissorOffset);
1191 glm::ivec2 extent = glm::min(titleRectOffset+glm::ivec2(renderObject.pclient->titleRect.w,renderObject.pclient->titleRect.h),scissorOffset+glm::ivec2(scissor.extent.width,scissor.extent.height))-offset;
1192
1193 if(glm::all(glm::greaterThan(extent,glm::ivec2(0)))){
1194 VkRect2D textFrame;
1195 textFrame.offset = {offset.x,offset.y};
1196 textFrame.extent = {extent.x,extent.y};
1197
1198 vkCmdSetScissor(pcommandBuffers[currentFrame],0,1,&textFrame);
1199
1200 vkCmdBindPipeline(pcommandBuffers[currentFrame],VK_PIPELINE_BIND_POINT_GRAPHICS,renderObject.pclientFrame->ptitle->passignedSet->p->pipeline);
1201 //renderObject.pclientFrame->ptitle->Draw(titlePosition,(renderObject.pclient->pcontainer->pParent->flags & WManager::Container::FLAG_STACKED)?renderObject.pclient->pcontainer->pParent->titleTransform:renderObject.pclient->pcontainer->titleTransform,&pcommandBuffers[currentFrame]);
1202 renderObject.pclientFrame->ptitle->Draw(titlePosition,renderObject.pclient->pcontainer->titleTransform,&pcommandBuffers[currentFrame]);
1203
1204 vkCmdSetScissor(pcommandBuffers[currentFrame],0,1,&scissor);
1205 }
1206 }
1207 }
1208
1209 vkCmdEndRenderPass(pcommandBuffers[currentFrame]);
1210
1211 if(vkEndCommandBuffer(pcommandBuffers[currentFrame]) != VK_SUCCESS)
1212 throw Exception("Failed to end command buffer recording.");
1213 }
1214
Present()1215 void CompositorInterface::Present(){
1216 if(unredirected || !frameApproval)
1217 return;
1218
1219 VkPipelineStageFlags pipelineStageFlags[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
1220 //VkPipelineStageFlags pipelineStageFlags[] = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
1221
1222 VkSubmitInfo submitInfo = {};
1223 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1224 submitInfo.commandBufferCount = 1;
1225 submitInfo.pCommandBuffers = &pcopyCommandBuffers[currentFrame];
1226 if(vkQueueSubmit(queue[QUEUE_INDEX_GRAPHICS],1,&submitInfo,0) != VK_SUCCESS)
1227 throw Exception("Failed to submit a queue.");
1228
1229 submitInfo.waitSemaphoreCount = 1;
1230 submitInfo.pWaitSemaphores = &psemaphore[currentFrame][SEMAPHORE_INDEX_IMAGE_AVAILABLE];
1231 submitInfo.pWaitDstStageMask = pipelineStageFlags;
1232 submitInfo.signalSemaphoreCount = 1;
1233 submitInfo.pSignalSemaphores = &psemaphore[currentFrame][SEMAPHORE_INDEX_RENDER_FINISHED];
1234 submitInfo.commandBufferCount = 1;
1235 submitInfo.pCommandBuffers = &pcommandBuffers[currentFrame];
1236 if(vkQueueSubmit(queue[QUEUE_INDEX_GRAPHICS],1,&submitInfo,pfence[currentFrame]) != VK_SUCCESS)
1237 throw Exception("Failed to submit a queue.");
1238
1239 VkPresentRegionKHR presentRegion = {};
1240 presentRegion.rectangleCount = presentRectLayers.size();
1241 presentRegion.pRectangles = presentRectLayers.data();
1242
1243 VkPresentRegionsKHR presentRegions = {};
1244 presentRegions.sType = VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR;
1245 presentRegions.swapchainCount = 1;
1246 presentRegions.pRegions = &presentRegion;
1247
1248 VkPresentInfoKHR presentInfo = {};
1249 presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
1250 presentInfo.waitSemaphoreCount = 1;
1251 presentInfo.pWaitSemaphores = &psemaphore[currentFrame][SEMAPHORE_INDEX_RENDER_FINISHED];
1252 presentInfo.swapchainCount = 1;
1253 presentInfo.pSwapchains = &swapChain;
1254 presentInfo.pImageIndices = &imageIndex;
1255 presentInfo.pResults = 0;
1256 presentInfo.pNext = presentRegion.rectangleCount > 0?&presentRegions:0;
1257 vkQueuePresentKHR(queue[QUEUE_INDEX_PRESENT],&presentInfo);
1258
1259 presentRectLayers.clear();
1260
1261 currentFrame = (currentFrame+1)%swapChainImageCount;
1262
1263 frameTag++;
1264 }
1265
1266 //-vertex buffer layout is always fixed, since there is no predefined information on what shaders (and thus inputs) will be used on what vertex data
1267 //TODO: take out 'new Pipeline' from below, move it outside - no need to template this
1268 template<class T>
LoadPipeline(const char * pshaderName[Pipeline::SHADER_MODULE_COUNT],const std::vector<std::pair<ShaderModule::INPUT,uint>> * pvertexBufferLayout)1269 Pipeline * CompositorInterface::LoadPipeline(const char *pshaderName[Pipeline::SHADER_MODULE_COUNT], const std::vector<std::pair<ShaderModule::INPUT,uint>> *pvertexBufferLayout){
1270 size_t hash = typeid(T).hash_code();
1271 for(uint i = 0; i < Pipeline::SHADER_MODULE_COUNT; ++i)
1272 if(pshaderName[i])
1273 boost::hash_combine(hash,std::string(pshaderName[i]));
1274 if(pvertexBufferLayout)
1275 boost::hash_range(hash,pvertexBufferLayout->begin(),pvertexBufferLayout->end());
1276
1277 auto m = std::find_if(pipelines.begin(),pipelines.end(),[&](auto &r)->bool{
1278 return r.first == hash;
1279 });
1280 if(m != pipelines.end())
1281 return (*m).second;
1282
1283 ShaderModule *pshader[Pipeline::SHADER_MODULE_COUNT] = {};
1284 for(uint i = 0; i < Pipeline::SHADER_MODULE_COUNT; ++i){
1285 if(!pshaderName[i])
1286 continue;
1287 auto n = std::find_if(shaders.begin(),shaders.end(),[&](auto &r)->bool{
1288 return strcmp(r.pname,pshaderName[i]) == 0;
1289 });
1290 if(n == shaders.end()){
1291 snprintf(Exception::buffer,sizeof(Exception::buffer),"Shader not found: %s.",pshaderName[i]);
1292 throw Exception();
1293 }
1294 pshader[i] = &(*n);
1295 }
1296 Pipeline *pPipeline = new T(
1297 pshader[Pipeline::SHADER_MODULE_VERTEX],
1298 pshader[Pipeline::SHADER_MODULE_GEOMETRY],
1299 pshader[Pipeline::SHADER_MODULE_FRAGMENT],pvertexBufferLayout,this);
1300 pipelines.push_back(std::pair<size_t, Pipeline *>(hash,pPipeline));
1301
1302 return pPipeline;
1303 }
1304
1305 template Pipeline * CompositorInterface::LoadPipeline<ClientPipeline>(const char *[Pipeline::SHADER_MODULE_COUNT], const std::vector<std::pair<ShaderModule::INPUT,uint>> *);
1306 template Pipeline * CompositorInterface::LoadPipeline<TextPipeline>(const char *[Pipeline::SHADER_MODULE_COUNT], const std::vector<std::pair<ShaderModule::INPUT,uint>> *);
1307
ClearBackground()1308 void CompositorInterface::ClearBackground(){
1309 ClientFrame *pbackground1 = dynamic_cast<ClientFrame *>(pbackground);
1310 if(pbackground1)
1311 delete pbackground1;
1312 if(!pcolorBackground){
1313 static const char *pshaderName[Pipeline::SHADER_MODULE_COUNT] = {
1314 "default_vertex.spv","default_geometry.spv","solid_fragment.spv"
1315 };
1316 pcolorBackground = new ColorFrame(pshaderName,this);
1317 }
1318
1319 pbackground = pcolorBackground;
1320
1321 VkRect2D screenRect;
1322 screenRect.offset = {0,0};
1323 screenRect.extent = imageExtent;
1324 AddDamageRegion(&screenRect);
1325 }
1326
CreateTexture(uint w,uint h,uint surfaceDepth)1327 Texture * CompositorInterface::CreateTexture(uint w, uint h, uint surfaceDepth){
1328 Texture *ptexture;
1329
1330 //should be larger than 0:
1331 w = std::max(std::min(w,physicalDevProps.limits.maxImageDimension2D),1u);
1332 h = std::max(std::min(h,physicalDevProps.limits.maxImageDimension2D),1u);
1333
1334 const VkComponentMapping *pcomponentMapping = surfaceDepth > 24?&TexturePixmap::pixmapComponentMapping:&TexturePixmap::pixmapComponentMapping24;
1335 uint componentMappingHash = TextureBase::GetComponentMappingHash(pcomponentMapping);
1336
1337 auto m = std::find_if(textureCache.begin(),textureCache.end(),[&](auto &r)->bool{
1338 //return r.ptexture->w == w && r.ptexture->h == h;
1339 return r.ptexture->w == w && r.ptexture->h == h && r.ptexture->componentMappingHash == componentMappingHash;
1340 });
1341 if(m != textureCache.end()){
1342 ptexture = (*m).ptexture;
1343
1344 std::iter_swap(m,textureCache.end()-1);
1345 textureCache.pop_back();
1346 printf("----------- found cached texture\n");
1347
1348 }else ptexture = new Texture(w,h,pcomponentMapping,0,this);
1349
1350 return ptexture;
1351 }
1352
ReleaseTexture(Texture * ptexture)1353 void CompositorInterface::ReleaseTexture(Texture *ptexture){
1354 TextureCacheEntry textureCacheEntry;
1355 textureCacheEntry.ptexture = ptexture;
1356 textureCacheEntry.releaseTag = frameTag;
1357 clock_gettime(CLOCK_MONOTONIC,&textureCacheEntry.releaseTime);
1358
1359 textureCache.push_back(textureCacheEntry); //->emplace_back
1360 }
1361
CreateDescSets(const ShaderModule * pshaderModule)1362 VkDescriptorSet * CompositorInterface::CreateDescSets(const ShaderModule *pshaderModule){
1363 VkDescriptorSet *pdescSets = new VkDescriptorSet[pshaderModule->setCount];
1364
1365 for(VkDescriptorPool &descPool : descPoolArray){
1366 VkDescriptorSetAllocateInfo descSetAllocateInfo = {};
1367 descSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
1368 descSetAllocateInfo.descriptorPool = descPool;
1369 descSetAllocateInfo.pSetLayouts = pshaderModule->pdescSetLayouts;
1370 descSetAllocateInfo.descriptorSetCount = pshaderModule->setCount;
1371 if(vkAllocateDescriptorSets(logicalDev,&descSetAllocateInfo,pdescSets) == VK_SUCCESS){
1372 descPoolReference.push_back(std::pair<VkDescriptorSet *, VkDescriptorPool>(pdescSets,descPool));
1373 return pdescSets;
1374 }
1375 }
1376
1377 VkDescriptorPoolSize descPoolSizes[2];
1378 descPoolSizes[0] = (VkDescriptorPoolSize){};
1379 descPoolSizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLER;//VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1380 descPoolSizes[0].descriptorCount = 16;
1381
1382 descPoolSizes[1] = (VkDescriptorPoolSize){};
1383 descPoolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1384 descPoolSizes[1].descriptorCount = 16;
1385
1386 VkDescriptorPool descPool;
1387
1388 //if there are no pools or they are all out of memory, attempt to create a new one
1389 VkDescriptorPoolCreateInfo descPoolCreateInfo = {};
1390 descPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
1391 descPoolCreateInfo.poolSizeCount = sizeof(descPoolSizes)/sizeof(descPoolSizes[0]);
1392 descPoolCreateInfo.pPoolSizes = descPoolSizes;
1393 descPoolCreateInfo.maxSets = 16;
1394 descPoolCreateInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1395 if(vkCreateDescriptorPool(logicalDev,&descPoolCreateInfo,0,&descPool) != VK_SUCCESS){
1396 delete []pdescSets;
1397 return 0;
1398 }
1399 descPoolArray.push_front(descPool);
1400
1401 VkDescriptorSetAllocateInfo descSetAllocateInfo = {};
1402 descSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
1403 descSetAllocateInfo.descriptorPool = descPool;
1404 descSetAllocateInfo.pSetLayouts = pshaderModule->pdescSetLayouts;
1405 descSetAllocateInfo.descriptorSetCount = pshaderModule->setCount;
1406 if(vkAllocateDescriptorSets(logicalDev,&descSetAllocateInfo,pdescSets) == VK_SUCCESS){
1407 descPoolReference.push_back(std::pair<VkDescriptorSet *, VkDescriptorPool>(pdescSets,descPool));
1408 return pdescSets;
1409 }
1410
1411 delete []pdescSets;
1412 return 0;
1413 }
1414
ReleaseDescSets(const ShaderModule * pshaderModule,VkDescriptorSet * pdescSets)1415 void CompositorInterface::ReleaseDescSets(const ShaderModule *pshaderModule, VkDescriptorSet *pdescSets){
1416 DescSetCacheEntry descSetCacheEntry;
1417 descSetCacheEntry.pdescSets = pdescSets;
1418 descSetCacheEntry.setCount = pshaderModule->setCount;
1419 descSetCacheEntry.releaseTag = frameTag;
1420
1421 descSetCache.push_back(descSetCacheEntry);
1422 }
1423
ValidationLayerDebugCallback(VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT objType,uint64_t obj,size_t location,int32_t code,const char * playerPrefix,const char * pmsg,void * puserData)1424 VKAPI_ATTR VkBool32 VKAPI_CALL CompositorInterface::ValidationLayerDebugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t obj, size_t location, int32_t code, const char *playerPrefix, const char *pmsg, void *puserData){
1425 DebugPrintf(stdout,"validation layer: %s\n",pmsg);
1426 return VK_FALSE;
1427 }
1428
ValidationLayerDebugCallback2(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageType,const VkDebugUtilsMessengerCallbackDataEXT * pdata,void * puserData)1429 VKAPI_ATTR VkBool32 VKAPI_CALL CompositorInterface::ValidationLayerDebugCallback2(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pdata, void *puserData){
1430 DebugPrintf(stdout,"validation layer2: %s\n",pdata->pMessage);
1431 return VK_FALSE;
1432 }
1433
1434 //X11ClientFrame::X11ClientFrame(WManager::Container *pcontainer, const Backend::X11Client::CreateInfo *_pcreateInfo, const char *_pshaderName[Pipeline::SHADER_MODULE_COUNT], CompositorInterface *_pcomp) : X11Client(pcontainer,_pcreateInfo), ClientFrame(_pshaderName,_pcomp){
X11ClientFrame(Backend::X11Container * pcontainer,const Backend::X11Client::CreateInfo * _pcreateInfo,const char * _pshaderName[Pipeline::SHADER_MODULE_COUNT],CompositorInterface * _pcomp)1435 X11ClientFrame::X11ClientFrame(Backend::X11Container *pcontainer, const Backend::X11Client::CreateInfo *_pcreateInfo, const char *_pshaderName[Pipeline::SHADER_MODULE_COUNT], CompositorInterface *_pcomp) : X11Client(pcontainer,_pcreateInfo), ClientFrame(_pshaderName,_pcomp){
1436 //xcb_composite_redirect_window(pbackend->pcon,window,XCB_COMPOSITE_REDIRECT_MANUAL);
1437 windowPixmap = xcb_generate_id(pbackend->pcon);
1438
1439 Backend::X11Container *proot11 = static_cast<Backend::X11Container *>(pcontainer->GetRoot());
1440 if(!proot11->noComp){
1441 Redirect1();
1442 StartComposition1();
1443 }
1444 }
1445
~X11ClientFrame()1446 X11ClientFrame::~X11ClientFrame(){
1447 StopComposition1();
1448 Unredirect1();
1449
1450 if(this == pcomp->pfsAppPrev)
1451 pcomp->pfsAppPrev = 0;
1452 //xcb_composite_unredirect_window(pbackend->pcon,window,XCB_COMPOSITE_REDIRECT_MANUAL);
1453 }
1454
UpdateContents(const VkCommandBuffer * pcommandBuffer)1455 void X11ClientFrame::UpdateContents(const VkCommandBuffer *pcommandBuffer){
1456 //
1457 damageRegions.erase(std::remove_if(damageRegions.begin(),damageRegions.end(),[&](const VkRect2D &rect1)->bool{
1458 return rect.w < rect1.offset.x+rect1.extent.width || rect.h < rect1.offset.y+rect1.extent.height;
1459 }),damageRegions.end());
1460
1461 if(!fullRegionUpdate && damageRegions.size() == 0)
1462 return;
1463
1464 if(fullRegionUpdate){
1465 damageRegions.clear();
1466
1467 VkRect2D rect1;
1468 rect1.offset = {0,0};
1469 rect1.extent = {rect.w,rect.h};
1470 damageRegions.push_back(rect1);
1471
1472 fullRegionUpdate = false;
1473 }
1474
1475 if(!pcomp->hostMemoryImport){
1476 unsigned char *pdata = (unsigned char *)ptexture->Map();
1477
1478 for(VkRect2D &rect1 : damageRegions){
1479 xcb_shm_get_image_cookie_t imageCookie = xcb_shm_get_image(pbackend->pcon,windowPixmap,rect1.offset.x,rect1.offset.y,rect1.extent.width,rect1.extent.height,~0u,XCB_IMAGE_FORMAT_Z_PIXMAP,segment,0);
1480
1481 //wait for the buffers to get updated before copying them
1482 xcb_shm_get_image_reply_t *pimageReply = xcb_shm_get_image_reply(pbackend->pcon,imageCookie,0);
1483 xcb_flush(pbackend->pcon);
1484 free(pimageReply);
1485
1486 for(uint y = 0; y < rect1.extent.height; ++y){
1487 uint offsetDst = 4*(rect.w*(y+rect1.offset.y)+rect1.offset.x);
1488 uint offsetSrc = 4*(rect1.extent.width*y);
1489 memcpy(pdata+offsetDst,pchpixels+offsetSrc,4*rect1.extent.width);
1490 }
1491
1492 VkRect2D screenRect;
1493 screenRect.offset = {(sint)position.x+rect1.offset.x,(sint)position.y+rect1.offset.y};
1494 screenRect.extent = rect1.extent;
1495 pcomp->AddDamageRegion(&screenRect);
1496 }
1497 ptexture->Unmap(pcommandBuffer,damageRegions.data(),damageRegions.size());
1498
1499 }else{
1500 xcb_shm_get_image_cookie_t imageCookie = xcb_shm_get_image(pbackend->pcon,windowPixmap,0,0,rect.w,rect.h,~0u,XCB_IMAGE_FORMAT_Z_PIXMAP,segment,0); //need to get whole image
1501
1502 //wait for the buffers to get updated before copying them
1503 xcb_shm_get_image_reply_t *pimageReply = xcb_shm_get_image_reply(pbackend->pcon,imageCookie,0);
1504 xcb_flush(pbackend->pcon);
1505 free(pimageReply);
1506
1507 for(VkRect2D &rect1 : damageRegions){
1508 VkRect2D screenRect;
1509 screenRect.offset = {(sint)position.x+rect1.offset.x,(sint)position.y+rect1.offset.y};
1510 screenRect.extent = rect1.extent;
1511 pcomp->AddDamageRegion(&screenRect);
1512 }
1513
1514 ptexture->Update(pcommandBuffer,damageRegions.data(),damageRegions.size());
1515 }
1516
1517 damageRegions.clear();
1518 }
1519
Exclude(bool exclude)1520 void X11ClientFrame::Exclude(bool exclude){
1521 if(exclude){
1522 StopComposition1();
1523 Unredirect1();
1524 }else{
1525 Redirect1();
1526 StartComposition1();
1527 }
1528 }
1529
AdjustSurface1()1530 void X11ClientFrame::AdjustSurface1(){
1531 if(!enabled)
1532 return;
1533 if(oldRect.w != rect.w || oldRect.h != rect.h){
1534 //detach
1535 if(pcomp->hostMemoryImport)
1536 ptexture->Detach(pcomp->frameTag);
1537 xcb_shm_detach(pbackend->pcon,segment);
1538 shmdt(pchpixels);
1539
1540 shmctl(shmid,IPC_RMID,0);
1541
1542 //attach
1543 uint textureSize = rect.w*rect.h*4;
1544 shmid = shmget(IPC_PRIVATE,(textureSize-1)+pcomp->physicalDevExternalMemoryHostProps.minImportedHostPointerAlignment-(textureSize-1)%pcomp->physicalDevExternalMemoryHostProps.minImportedHostPointerAlignment,IPC_CREAT|0777);
1545 if(shmid == -1){
1546 DebugPrintf(stderr,"Failed to allocate shared memory.\n");
1547 return;
1548 }
1549 xcb_shm_attach(pbackend->pcon,segment,shmid,0);
1550 pchpixels = (unsigned char*)shmat(shmid,0,0);
1551
1552 xcb_free_pixmap(pbackend->pcon,windowPixmap);
1553 xcb_composite_name_window_pixmap(pbackend->pcon,window,windowPixmap);
1554
1555 AdjustSurface(rect.w,rect.h);
1556
1557 if(pcomp->hostMemoryImport && !ptexture->Attach(pchpixels)){
1558 DebugPrintf(stderr,"Failed to import host memory. Disabling feature.\n");
1559 pcomp->hostMemoryImport = false;
1560 }
1561
1562 pcomp->AddDamageRegion(this);
1563 }else
1564 if(oldRect.x != rect.x || oldRect.y != rect.y)
1565 pcomp->AddDamageRegion(this);
1566 }
1567
Redirect1()1568 void X11ClientFrame::Redirect1(){
1569 //
1570 xcb_composite_redirect_window(pbackend->pcon,window,XCB_COMPOSITE_REDIRECT_MANUAL);
1571 }
1572
StartComposition1()1573 void X11ClientFrame::StartComposition1(){
1574 if(enabled)
1575 return;
1576 xcb_composite_name_window_pixmap(pbackend->pcon,window,windowPixmap);
1577
1578 damage = xcb_generate_id(pbackend->pcon);
1579 xcb_damage_create(pbackend->pcon,damage,window,XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
1580
1581 //attach to shared memory
1582 uint textureSize = rect.w*rect.h*4;
1583 shmid = shmget(IPC_PRIVATE,(textureSize-1)+pcomp->physicalDevExternalMemoryHostProps.minImportedHostPointerAlignment-(textureSize-1)%pcomp->physicalDevExternalMemoryHostProps.minImportedHostPointerAlignment,IPC_CREAT|0777);
1584 if(shmid == -1){
1585 DebugPrintf(stderr,"Failed to allocate shared memory.\n");
1586 return;
1587 }
1588 segment = xcb_generate_id(pbackend->pcon);
1589 xcb_shm_attach(pbackend->pcon,segment,shmid,0);
1590 pchpixels = (unsigned char*)shmat(shmid,0,0);
1591
1592 xcb_flush(pbackend->pcon);
1593
1594 //get image depth
1595 xcb_shm_get_image_cookie_t imageCookie = xcb_shm_get_image(pbackend->pcon,windowPixmap,0,0,1,1,~0u,XCB_IMAGE_FORMAT_Z_PIXMAP,segment,0);
1596 xcb_shm_get_image_reply_t *pimageReply = xcb_shm_get_image_reply(pbackend->pcon,imageCookie,0);
1597
1598 uint depth;
1599 if(pimageReply){
1600 depth = pimageReply->depth;
1601 free(pimageReply);
1602 }else{
1603 DebugPrintf(stderr,"Failed to get SHM image. Assuming 24 bit depth.\n");
1604 depth = 24;
1605 }
1606
1607 CreateSurface(rect.w,rect.h,depth);
1608
1609 if(pcomp->hostMemoryImport && !ptexture->Attach(pchpixels)){
1610 DebugPrintf(stderr,"Failed to import host memory. Disabling feature.\n");
1611 pcomp->hostMemoryImport = false;
1612 }
1613
1614 pcomp->AddDamageRegion(this);
1615 enabled = true;
1616 }
1617
Unredirect1()1618 void X11ClientFrame::Unredirect1(){
1619 //
1620 xcb_composite_unredirect_window(pbackend->pcon,window,XCB_COMPOSITE_REDIRECT_MANUAL);
1621 }
1622
StopComposition1()1623 void X11ClientFrame::StopComposition1(){
1624 if(!enabled)
1625 return;
1626 if(pcomp->hostMemoryImport)
1627 ptexture->Detach(pcomp->frameTag);
1628
1629 xcb_shm_detach(pbackend->pcon,segment);
1630 shmdt(pchpixels);
1631
1632 shmctl(shmid,IPC_RMID,0);
1633
1634 xcb_damage_destroy(pbackend->pcon,damage);
1635
1636 xcb_free_pixmap(pbackend->pcon,windowPixmap);
1637
1638 DestroySurface();
1639
1640 pcomp->AddDamageRegion(this);
1641 enabled = false;
1642 }
1643
SetTitle1(const char * ptitle)1644 void X11ClientFrame::SetTitle1(const char *ptitle){
1645 SetTitle(ptitle);
1646
1647 VkRect2D rect;
1648 rect.offset = {titleRect.x,titleRect.y};
1649 rect.extent = {titleRect.w,titleRect.h};
1650 pcomp->AddDamageRegion(&rect);
1651 }
1652
X11Background(xcb_pixmap_t _pixmap,uint _w,uint _h,const char * _pshaderName[Pipeline::SHADER_MODULE_COUNT],X11Compositor * _pcomp)1653 X11Background::X11Background(xcb_pixmap_t _pixmap, uint _w, uint _h, const char *_pshaderName[Pipeline::SHADER_MODULE_COUNT], X11Compositor *_pcomp) : w(_w), h(_h), ClientFrame(_pshaderName,_pcomp), pcomp11(_pcomp), pixmap(_pixmap){
1654 //
1655 uint textureSize = w*h*4;
1656 shmid = shmget(IPC_PRIVATE,(textureSize-1)+pcomp->physicalDevExternalMemoryHostProps.minImportedHostPointerAlignment-(textureSize-1)%pcomp->physicalDevExternalMemoryHostProps.minImportedHostPointerAlignment,IPC_CREAT|0777);
1657 if(shmid == -1){
1658 DebugPrintf(stderr,"Failed to allocate shared memory.\n");
1659 return;
1660 }
1661 segment = xcb_generate_id(pcomp11->pbackend->pcon);
1662 xcb_shm_attach(pcomp11->pbackend->pcon,segment,shmid,0);
1663
1664 pchpixels = (unsigned char*)shmat(shmid,0,0);
1665
1666 CreateSurface(w,h,24);
1667
1668 if(pcomp->hostMemoryImport && !ptexture->Attach(pchpixels)){
1669 DebugPrintf(stderr,"Failed to import host memory. Disabling feature.\n");
1670 pcomp->hostMemoryImport = false;
1671 }
1672
1673 VkRect2D screenRect;
1674 screenRect.offset = {0,0};
1675 screenRect.extent = {w,h};
1676 pcomp->AddDamageRegion(&screenRect);
1677 }
1678
~X11Background()1679 X11Background::~X11Background(){
1680 if(pcomp->hostMemoryImport)
1681 ptexture->Detach(pcomp->frameTag);
1682
1683 xcb_shm_detach(pcomp11->pbackend->pcon,segment);
1684 shmdt(pchpixels);
1685
1686 shmctl(shmid,IPC_RMID,0);
1687
1688 VkRect2D screenRect;
1689 screenRect.offset = {0,0};
1690 screenRect.extent = {w,h};
1691 pcomp->AddDamageRegion(&screenRect);
1692 }
1693
UpdateContents(const VkCommandBuffer * pcommandBuffer)1694 void X11Background::UpdateContents(const VkCommandBuffer *pcommandBuffer){
1695 if(!fullRegionUpdate)
1696 return;
1697
1698 xcb_shm_get_image_cookie_t imageCookie = xcb_shm_get_image(pcomp11->pbackend->pcon,pixmap,0,0,w,h,~0u,XCB_IMAGE_FORMAT_Z_PIXMAP,segment,0);
1699
1700 xcb_shm_get_image_reply_t *pimageReply = xcb_shm_get_image_reply(pcomp11->pbackend->pcon,imageCookie,0);
1701 xcb_flush(pcomp11->pbackend->pcon);
1702
1703 if(!pimageReply){
1704 DebugPrintf(stderr,"No shared memory.\n");
1705 return;
1706 }
1707
1708 free(pimageReply);
1709
1710 VkRect2D screenRect;
1711 screenRect.offset = {0,0};
1712 screenRect.extent = {w,h};
1713
1714 if(!pcomp->hostMemoryImport){
1715 unsigned char *pdata = (unsigned char*)ptexture->Map();
1716 memcpy(pdata,pchpixels,w*h*4);
1717
1718 ptexture->Unmap(pcommandBuffer,&screenRect,1);
1719
1720 }else{
1721 ptexture->Update(pcommandBuffer,&screenRect,1);
1722 }
1723
1724 fullRegionUpdate = false;
1725
1726 pcomp->AddDamageRegion(&screenRect);
1727 }
1728
X11Compositor(const Configuration * _pconfig,const Backend::X11Backend * _pbackend)1729 X11Compositor::X11Compositor(const Configuration *_pconfig, const Backend::X11Backend *_pbackend) : CompositorInterface(_pconfig), pbackend(_pbackend){
1730 //
1731 }
1732
~X11Compositor()1733 X11Compositor::~X11Compositor(){
1734 //
1735 }
1736
Start()1737 void X11Compositor::Start(){
1738 //compositor
1739 if(!pbackend->QueryExtension("Composite",&compEventOffset,&compErrorOffset))
1740 throw Exception("XCompositor unavailable.");
1741 xcb_composite_query_version_cookie_t compCookie = xcb_composite_query_version(pbackend->pcon,XCB_COMPOSITE_MAJOR_VERSION,XCB_COMPOSITE_MINOR_VERSION);
1742 xcb_composite_query_version_reply_t *pcompReply = xcb_composite_query_version_reply(pbackend->pcon,compCookie,0);
1743 if(!pcompReply)
1744 throw Exception("XCompositor unavailable.");
1745 DebugPrintf(stdout,"XComposite %u.%u\n",pcompReply->major_version,pcompReply->minor_version);
1746 free(pcompReply);
1747
1748 //overlay
1749 xcb_composite_get_overlay_window_cookie_t overlayCookie = xcb_composite_get_overlay_window(pbackend->pcon,pbackend->pscr->root);
1750 xcb_composite_get_overlay_window_reply_t *poverlayReply = xcb_composite_get_overlay_window_reply(pbackend->pcon,overlayCookie,0);
1751 if(!poverlayReply)
1752 throw Exception("Unable to get overlay window.");
1753 overlay = poverlayReply->overlay_win;
1754 free(poverlayReply);
1755 DebugPrintf(stdout,"overlay xid: %u\n",overlay);
1756
1757 uint mask = XCB_CW_EVENT_MASK;
1758 uint values[1] = {XCB_EVENT_MASK_EXPOSURE};
1759 xcb_change_window_attributes(pbackend->pcon,overlay,mask,values);
1760
1761 //xfixes
1762 if(!pbackend->QueryExtension("XFIXES",&xfixesEventOffset,&xfixesErrorOffset))
1763 throw Exception("XFixes unavailable.");
1764 xcb_xfixes_query_version_cookie_t fixesCookie = xcb_xfixes_query_version(pbackend->pcon,XCB_XFIXES_MAJOR_VERSION,XCB_XFIXES_MINOR_VERSION);
1765 xcb_xfixes_query_version_reply_t *pfixesReply = xcb_xfixes_query_version_reply(pbackend->pcon,fixesCookie,0);
1766 if(!pfixesReply)
1767 throw Exception("XFixes unavailable.");
1768 DebugPrintf(stdout,"XFixes %u.%u\n",pfixesReply->major_version,pfixesReply->minor_version);
1769 free(pfixesReply);
1770
1771 //allow overlay input passthrough
1772 xcb_xfixes_region_t region = xcb_generate_id(pbackend->pcon);
1773 xcb_void_cookie_t regionCookie = xcb_xfixes_create_region_checked(pbackend->pcon,region,0,0);
1774 xcb_generic_error_t *perr = xcb_request_check(pbackend->pcon,regionCookie);
1775 if(perr != 0){
1776 snprintf(Exception::buffer,sizeof(Exception::buffer),"Unable to create overlay region (%d).",perr->error_code);
1777 throw Exception();
1778 }
1779 xcb_discard_reply(pbackend->pcon,regionCookie.sequence);
1780 xcb_xfixes_set_window_shape_region(pbackend->pcon,overlay,XCB_SHAPE_SK_BOUNDING,0,0,XCB_XFIXES_REGION_NONE);
1781 xcb_xfixes_set_window_shape_region(pbackend->pcon,overlay,XCB_SHAPE_SK_INPUT,0,0,region);
1782 xcb_xfixes_destroy_region(pbackend->pcon,region);
1783
1784 //damage
1785 if(!pbackend->QueryExtension("DAMAGE",&damageEventOffset,&damageErrorOffset))
1786 throw Exception("Damage extension unavailable.");
1787
1788 xcb_damage_query_version_cookie_t damageCookie = xcb_damage_query_version(pbackend->pcon,XCB_DAMAGE_MAJOR_VERSION,XCB_DAMAGE_MINOR_VERSION);
1789 xcb_damage_query_version_reply_t *pdamageReply = xcb_damage_query_version_reply(pbackend->pcon,damageCookie,0);
1790 if(!pdamageReply)
1791 throw Exception("Damage extension unavailable.");
1792 DebugPrintf(stdout,"Damage %u.%u\n",pdamageReply->major_version,pdamageReply->minor_version);
1793 free(pdamageReply);
1794
1795 xcb_shm_query_version_cookie_t shmCookie = xcb_shm_query_version(pbackend->pcon);
1796 xcb_shm_query_version_reply_t *pshmReply = xcb_shm_query_version_reply(pbackend->pcon,shmCookie,0);
1797 if(!pshmReply || !pshmReply->shared_pixmaps)
1798 throw Exception("SHM extension unavailable.");
1799 DebugPrintf(stdout,"SHM %u.%u\n",pshmReply->major_version,pshmReply->minor_version);
1800 free(pshmReply);
1801
1802 xcb_dri3_query_version_cookie_t dri3Cookie = xcb_dri3_query_version(pbackend->pcon,XCB_DRI3_MAJOR_VERSION,XCB_DRI3_MINOR_VERSION);
1803 xcb_dri3_query_version_reply_t *pdri3Reply = xcb_dri3_query_version_reply(pbackend->pcon,dri3Cookie,0);
1804 if(!pdri3Reply)
1805 throw Exception("DRI3 extension unavailable.");
1806 DebugPrintf(stdout,"DRI3 %u.%u\n",pdri3Reply->major_version,pdri3Reply->minor_version);
1807 free(pdri3Reply);
1808
1809 xcb_flush(pbackend->pcon);
1810
1811 InitializeRenderEngine();
1812
1813 /*char cardStr[256];
1814 snprintf(cardStr,sizeof(cardStr),"/dev/dri/card%u",physicalDevIndex);
1815
1816 cardfd = open(cardStr,O_RDWR|FD_CLOEXEC);
1817 if(cardfd < 0){
1818 snprintf(Exception::buffer,sizeof(Exception::buffer),"Failed to open %s",cardStr);
1819 throw Exception();
1820 }
1821 pgbmdev = gbm_create_device(cardfd);
1822 if(!pgbmdev)
1823 throw Exception("Failed to create GBM device.");*/
1824 }
1825
Stop()1826 void X11Compositor::Stop(){
1827 if(dynamic_cast<ClientFrame *>(pbackground))
1828 delete pbackground;
1829 if(pcolorBackground)
1830 delete pcolorBackground;
1831 DestroyRenderEngine();
1832
1833 /*gbm_device_destroy(pgbmdev);
1834 close(cardfd);*/
1835
1836 xcb_xfixes_set_window_shape_region(pbackend->pcon,overlay,XCB_SHAPE_SK_BOUNDING,0,0,XCB_XFIXES_REGION_NONE);
1837 xcb_xfixes_set_window_shape_region(pbackend->pcon,overlay,XCB_SHAPE_SK_INPUT,0,0,XCB_XFIXES_REGION_NONE);
1838
1839 xcb_composite_release_overlay_window(pbackend->pcon,overlay);
1840
1841 xcb_flush(pbackend->pcon);
1842 }
1843
Resume()1844 void X11Compositor::Resume(){
1845 if(!suspended)
1846 return;
1847 xcb_map_window(pbackend->pcon,overlay);
1848 xcb_flush(pbackend->pcon);
1849 suspended = false;
1850 }
1851
Suspend()1852 void X11Compositor::Suspend(){
1853 if(suspended)
1854 return;
1855 xcb_unmap_window(pbackend->pcon,overlay);
1856 xcb_flush(pbackend->pcon);
1857 suspended = true;
1858 }
1859
FilterEvent(const Backend::X11Event * pevent)1860 bool X11Compositor::FilterEvent(const Backend::X11Event *pevent){
1861 if(pevent->pevent->response_type == XCB_DAMAGE_NOTIFY+damageEventOffset){
1862 xcb_damage_notify_event_t *pev = (xcb_damage_notify_event_t*)pevent->pevent;
1863
1864 Backend::X11Client *pclient = pevent->pbackend->FindClient(pev->drawable,Backend::X11Backend::MODE_UNDEFINED);
1865 if(!pclient){
1866 DebugPrintf(stderr,"Unknown damage event.\n");
1867 return true;
1868 }
1869
1870 X11ClientFrame *pclientFrame = dynamic_cast<X11ClientFrame *>(pclient);
1871
1872 xcb_xfixes_region_t region = xcb_generate_id(pbackend->pcon);
1873 xcb_xfixes_create_region(pbackend->pcon,region,0,0);
1874 xcb_damage_subtract(pbackend->pcon,pclientFrame->damage,0,region);
1875
1876 xcb_xfixes_fetch_region_cookie_t fetchRegionCookie = xcb_xfixes_fetch_region_unchecked(pbackend->pcon,region);
1877 xcb_xfixes_destroy_region(pbackend->pcon,region);
1878
1879 xcb_xfixes_fetch_region_reply_t *pfetchRegionReply = xcb_xfixes_fetch_region_reply(pbackend->pcon,fetchRegionCookie,0);
1880
1881 if(!pfetchRegionReply || !pclientFrame->enabled){
1882 free(pfetchRegionReply);
1883 return true;
1884 }
1885
1886 uint count = xcb_xfixes_fetch_region_rectangles_length(pfetchRegionReply);
1887 if(count > 0){
1888 xcb_rectangle_t *prects = xcb_xfixes_fetch_region_rectangles(pfetchRegionReply);
1889 for(uint i = 0; i < count; ++i){
1890 if(pclient->rect.w >= prects[i].x+prects[i].width && pclient->rect.h >= prects[i].y+prects[i].height){
1891 VkRect2D rect;
1892 rect.offset = {prects[i].x,prects[i].y};
1893 rect.extent = {prects[i].width,prects[i].height};
1894 pclientFrame->damageRegions.push_back(rect);
1895 }
1896 }
1897 }else{
1898 if(pclient->rect.w >= pev->area.x+pev->area.width && pclient->rect.h >= pev->area.y+pev->area.height){
1899 VkRect2D rect;
1900 rect.offset = {pfetchRegionReply->extents.x,pfetchRegionReply->extents.y};
1901 rect.extent = {pfetchRegionReply->extents.width,pfetchRegionReply->extents.height};
1902 pclientFrame->damageRegions.push_back(rect);
1903 }
1904 }
1905
1906 free(pfetchRegionReply);
1907
1908 /*if(pclient->rect.w < pev->area.x+pev->area.width || pclient->rect.h < pev->area.y+pev->area.height)
1909 return true; //filter out outdated events after client shrink in size*/
1910
1911 if(std::find(updateQueue.begin(),updateQueue.end(),pclientFrame) == updateQueue.end())
1912 updateQueue.push_back(pclientFrame);
1913
1914 /*VkRect2D rect;
1915 rect.offset = {pev->area.x,pev->area.y};
1916 rect.extent = {pev->area.width,pev->area.height};
1917 pclientFrame->damageRegions.push_back(rect);
1918 //DebugPrintf(stdout,"DAMAGE_EVENT, %x, (%hd,%hd), (%hux%hu)\n",pev->drawable,pev->area.x,pev->area.y,pev->area.width,pev->area.height);*/
1919
1920 return true;
1921 }
1922
1923 return false;
1924 }
1925
CheckPresentQueueCompatibility(VkPhysicalDevice physicalDev,uint queueFamilyIndex) const1926 bool X11Compositor::CheckPresentQueueCompatibility(VkPhysicalDevice physicalDev, uint queueFamilyIndex) const{
1927 xcb_visualid_t visualid = pbackend->pscr->root_visual;
1928 return vkGetPhysicalDeviceXcbPresentationSupportKHR(physicalDev,queueFamilyIndex,pbackend->pcon,visualid) == VK_TRUE;
1929 }
1930
CreateSurfaceKHR(VkSurfaceKHR * psurface) const1931 void X11Compositor::CreateSurfaceKHR(VkSurfaceKHR *psurface) const{
1932 VkXcbSurfaceCreateInfoKHR xcbSurfaceCreateInfo = {};
1933 xcbSurfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
1934 xcbSurfaceCreateInfo.pNext = 0;
1935 xcbSurfaceCreateInfo.connection = pbackend->pcon; //pcon
1936 xcbSurfaceCreateInfo.window = overlay;
1937 if(vkCreateXcbSurfaceKHR(instance,&xcbSurfaceCreateInfo,0,psurface) != VK_SUCCESS)
1938 throw("Failed to create KHR surface.");
1939 }
1940
SetBackgroundPixmap(const Backend::BackendPixmapProperty * pPixmapProperty)1941 void X11Compositor::SetBackgroundPixmap(const Backend::BackendPixmapProperty *pPixmapProperty){
1942 if(pbackground){
1943 delete pbackground;
1944 pbackground = pcolorBackground;
1945 }
1946 if(pPixmapProperty->pixmap != 0){
1947 xcb_get_geometry_cookie_t geometryCookie = xcb_get_geometry(pbackend->pcon,pPixmapProperty->pixmap);
1948 xcb_get_geometry_reply_t *pgeometryReply = xcb_get_geometry_reply(pbackend->pcon,geometryCookie,0);
1949 if(!pgeometryReply)
1950 throw("Invalid geometry size - unable to retrieve.");
1951
1952 static const char *pshaderName[Pipeline::SHADER_MODULE_COUNT] = {
1953 "default_vertex.spv","default_geometry.spv","default_fragment.spv"
1954 };
1955 pbackground = new X11Background(pPixmapProperty->pixmap,pgeometryReply->width,pgeometryReply->height,pshaderName,this);
1956 printf("background set!\n");
1957 }
1958 }
1959
GetExtent() const1960 VkExtent2D X11Compositor::GetExtent() const{
1961 xcb_get_geometry_cookie_t geometryCookie = xcb_get_geometry(pbackend->pcon,overlay);
1962 xcb_get_geometry_reply_t *pgeometryReply = xcb_get_geometry_reply(pbackend->pcon,geometryCookie,0);
1963 if(!pgeometryReply)
1964 throw("Invalid geometry size - unable to retrieve.");
1965 VkExtent2D e = (VkExtent2D){pgeometryReply->width,pgeometryReply->height};
1966 free(pgeometryReply);
1967 return e;
1968 }
1969
GetDPI() const1970 glm::vec2 X11Compositor::GetDPI() const{
1971 return glm::vec2(25.4f*(float)pbackend->pscr->width_in_pixels/(float)pbackend->pscr->width_in_millimeters,25.4f*(float)pbackend->pscr->height_in_pixels/(float)pbackend->pscr->height_in_millimeters);
1972 }
1973
X11DebugClientFrame(Backend::DebugContainer * pcontainer,const Backend::DebugClient::CreateInfo * _pcreateInfo,const char * _pshaderName[Pipeline::SHADER_MODULE_COUNT],CompositorInterface * _pcomp)1974 X11DebugClientFrame::X11DebugClientFrame(Backend::DebugContainer *pcontainer, const Backend::DebugClient::CreateInfo *_pcreateInfo, const char *_pshaderName[Pipeline::SHADER_MODULE_COUNT], CompositorInterface *_pcomp) : DebugClient(pcontainer,_pcreateInfo), ClientFrame(_pshaderName,_pcomp){
1975 //
1976 StartComposition1();
1977 }
1978
~X11DebugClientFrame()1979 X11DebugClientFrame::~X11DebugClientFrame(){
1980 StopComposition1();
1981 }
1982
UpdateContents(const VkCommandBuffer * pcommandBuffer)1983 void X11DebugClientFrame::UpdateContents(const VkCommandBuffer *pcommandBuffer){
1984 //
1985 uint color[3];
1986 for(uint &t : color)
1987 t = rand()%190;
1988 unsigned char *pdata = (unsigned char*)ptexture->Map();
1989 for(uint i = 0, n = rect.w*rect.h; i < n; ++i){
1990 //unsigned char t = (float)(i/rect.w)/(float)rect.h*255;
1991 pdata[4*i+0] = color[0];
1992 pdata[4*i+1] = color[1];
1993 pdata[4*i+2] = color[2];
1994 pdata[4*i+3] = 190;//255;
1995 }
1996 VkRect2D rect1;
1997 rect1.offset = {0,0};
1998 rect1.extent = {rect.w,rect.h};
1999 ptexture->Unmap(pcommandBuffer,&rect1,1);
2000
2001 pcomp->AddDamageRegion(&rect1);
2002 }
2003
AdjustSurface1()2004 void X11DebugClientFrame::AdjustSurface1(){
2005 if(oldRect.w != rect.w || oldRect.h != rect.h){
2006 AdjustSurface(rect.w,rect.h);
2007 pcomp->AddDamageRegion(this);
2008 }else
2009 if(oldRect.x != rect.x || oldRect.y != rect.y)
2010 pcomp->AddDamageRegion(this);
2011 }
2012
Redirect1()2013 void X11DebugClientFrame::Redirect1(){
2014 //
2015 }
2016
StartComposition1()2017 void X11DebugClientFrame::StartComposition1(){
2018 if(enabled)
2019 return;
2020 CreateSurface(rect.w,rect.h,32);
2021 pcomp->AddDamageRegion(this);
2022 enabled = true;
2023 }
2024
Unredirect1()2025 void X11DebugClientFrame::Unredirect1(){
2026 //
2027 }
2028
StopComposition1()2029 void X11DebugClientFrame::StopComposition1(){
2030 if(!enabled)
2031 return;
2032 DestroySurface();
2033 pcomp->AddDamageRegion(this);
2034 enabled = false;
2035 }
2036
SetTitle1(const char * ptitle)2037 void X11DebugClientFrame::SetTitle1(const char *ptitle){
2038 SetTitle(ptitle);
2039
2040 VkRect2D rect;
2041 rect.offset = {titleRect.x,titleRect.y};
2042 rect.extent = {titleRect.w,titleRect.h};
2043 pcomp->AddDamageRegion(&rect);
2044 }
2045
X11DebugCompositor(const Configuration * _pconfig,const Backend::X11Backend * pbackend)2046 X11DebugCompositor::X11DebugCompositor(const Configuration *_pconfig, const Backend::X11Backend *pbackend) : X11Compositor(_pconfig,pbackend){
2047 //
2048 }
2049
~X11DebugCompositor()2050 X11DebugCompositor::~X11DebugCompositor(){
2051 //
2052 }
2053
Start()2054 void X11DebugCompositor::Start(){
2055 overlay = pbackend->window;
2056
2057 InitializeRenderEngine();
2058 }
2059
Stop()2060 void X11DebugCompositor::Stop(){
2061 DestroyRenderEngine();
2062 }
2063
Resume()2064 void X11DebugCompositor::Resume(){
2065 //
2066 }
2067
Suspend()2068 void X11DebugCompositor::Suspend(){
2069 //
2070 }
2071
NullCompositor()2072 NullCompositor::NullCompositor() : CompositorInterface(&config){
2073 //
2074 }
2075
~NullCompositor()2076 NullCompositor::~NullCompositor(){
2077 //
2078 }
2079
Start()2080 void NullCompositor::Start(){
2081 //
2082 }
2083
Stop()2084 void NullCompositor::Stop(){
2085 //
2086 }
2087
Resume()2088 void NullCompositor::Resume(){
2089 //
2090 }
2091
Suspend()2092 void NullCompositor::Suspend(){
2093 //
2094 }
CheckPresentQueueCompatibility(VkPhysicalDevice physicalDev,uint queueFamilyIndex) const2095 bool NullCompositor::CheckPresentQueueCompatibility(VkPhysicalDevice physicalDev, uint queueFamilyIndex) const{
2096 return true;
2097 }
2098
CreateSurfaceKHR(VkSurfaceKHR * psurface) const2099 void NullCompositor::CreateSurfaceKHR(VkSurfaceKHR *psurface) const{
2100 //
2101 }
2102
GetExtent() const2103 VkExtent2D NullCompositor::GetExtent() const{
2104 return (VkExtent2D){0,0};
2105 }
2106
GetDPI() const2107 glm::vec2 NullCompositor::GetDPI() const{
2108 return glm::vec2(0.0f);
2109 }
2110
2111 }
2112
2113