The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

c/renderer+ipc: Use layer renderer.

Make the renderer and IPC aware of multiple projection and quad layers
using the layer renderer.

Remove redundant code related to idle images and imported buffers and
command buffer rebuild, since we now always just display the layer
renderer's frame buffer.

Get view and projection properties from xrt_device.

authored by

Lubosz Sarnecki and committed by
Jakob Bornecrantz
d0539161 aedd4d9f

+282 -283
+6 -4
src/xrt/compositor/main/comp_compositor.c
··· 360 360 361 361 left = &stereo->l.sc->images[stereo->l.image_index]; 362 362 right = &stereo->l.sc->images[stereo->r.image_index]; 363 - uint32_t l_array_index = stereo->l.array_index; 364 - uint32_t r_array_index = stereo->r.array_index; 365 363 366 - comp_renderer_frame(c->r, left, l_array_index, right, r_array_index, 367 - layer->flip_y); 364 + comp_renderer_destroy_layers(c->r); 365 + comp_renderer_allocate_layers(c->r, 1); 366 + 367 + comp_renderer_set_projection_layer(c->r, left, right, layer->flip_y, 0); 368 + 369 + comp_renderer_draw(c->r); 368 370 369 371 compositor_add_frame_timing(c); 370 372
+100 -184
src/xrt/compositor/main/comp_renderer.c
··· 17 17 18 18 #include "xrt/xrt_compositor.h" 19 19 #include "main/comp_distortion.h" 20 - 20 + #include "main/comp_layer_renderer.h" 21 + #include "math/m_api.h" 21 22 22 23 /* 23 24 * ··· 32 33 */ 33 34 struct comp_renderer 34 35 { 35 - bool one_buffer_imported[2]; 36 - 37 36 uint32_t current_buffer; 38 37 39 38 VkQueue queue; ··· 52 51 VkFence *fences; 53 52 uint32_t num_buffers; 54 53 55 - struct comp_swapchain_image dummy_images[2]; 56 - 57 54 struct comp_compositor *c; 58 55 struct comp_settings *settings; 59 56 struct comp_distortion *distortion; 57 + 58 + struct comp_layer_renderer *lr; 60 59 }; 61 60 62 61 ··· 73 72 renderer_init(struct comp_renderer *r); 74 73 75 74 static void 76 - renderer_set_swapchain_image(struct comp_renderer *r, 77 - uint32_t eye, 78 - struct comp_swapchain_image *image, 79 - uint32_t layer, 80 - bool flip_y); 81 - 82 - static void 83 - renderer_render(struct comp_renderer *r); 84 - 85 - static void 86 75 renderer_submit_queue(struct comp_renderer *r); 87 76 88 77 static void 89 78 renderer_build_command_buffers(struct comp_renderer *r); 90 - 91 - static void 92 - renderer_rebuild_command_buffers(struct comp_renderer *r); 93 79 94 80 static void 95 81 renderer_build_command_buffer(struct comp_renderer *r, ··· 98 84 99 85 static void 100 86 renderer_init_descriptor_pool(struct comp_renderer *r); 101 - 102 - static void 103 - renderer_init_dummy_images(struct comp_renderer *r); 104 87 105 88 static void 106 89 renderer_create_frame_buffer(struct comp_renderer *r, ··· 157 140 } 158 141 159 142 void 160 - comp_renderer_frame(struct comp_renderer *r, 161 - struct comp_swapchain_image *left, 162 - uint32_t left_layer, 163 - struct comp_swapchain_image *right, 164 - uint32_t right_layer, 165 - bool flip_y) 166 - { 167 - renderer_set_swapchain_image(r, 0, left, left_layer, flip_y); 168 - renderer_set_swapchain_image(r, 1, right, right_layer, flip_y); 169 - renderer_render(r); 170 - } 171 - 172 - void 173 - comp_renderer_frame_cached(struct comp_renderer *r) 174 - { 175 - renderer_render(r); 176 - } 177 - 178 - void 179 143 comp_renderer_destroy(struct comp_renderer *r) 180 144 { 181 145 renderer_destroy(r); 182 146 free(r); 183 147 } 184 148 185 - void 186 - comp_renderer_reset(struct comp_renderer *r) 187 - { 188 - r->one_buffer_imported[0] = false; 189 - r->one_buffer_imported[1] = false; 190 - } 191 - 192 149 /* 193 150 * 194 151 * Functions. ··· 201 158 r->c = c; 202 159 r->settings = &c->settings; 203 160 204 - r->one_buffer_imported[0] = false; 205 - r->one_buffer_imported[1] = false; 206 161 r->current_buffer = 0; 207 162 r->queue = VK_NULL_HANDLE; 208 163 r->render_pass = VK_NULL_HANDLE; ··· 211 166 r->semaphores.present_complete = VK_NULL_HANDLE; 212 167 r->semaphores.render_complete = VK_NULL_HANDLE; 213 168 214 - U_ZERO(&r->dummy_images[0]); 215 - U_ZERO(&r->dummy_images[1]); 216 - r->dummy_images[0].views = U_TYPED_CALLOC(VkImageView); 217 - r->dummy_images[1].views = U_TYPED_CALLOC(VkImageView); 218 - 219 169 r->distortion = NULL; 220 170 r->cmd_buffers = NULL; 221 171 r->frame_buffers = NULL; ··· 264 214 for (uint32_t i = 0; i < r->num_buffers; ++i) 265 215 renderer_build_command_buffer(r, r->cmd_buffers[i], 266 216 r->frame_buffers[i]); 267 - } 268 - 269 - static void 270 - renderer_rebuild_command_buffers(struct comp_renderer *r) 271 - { 272 - renderer_destroy_command_buffers(r); 273 - 274 - r->num_buffers = r->c->window->swapchain.image_count; 275 - 276 - renderer_allocate_command_buffers(r); 277 - renderer_build_command_buffers(r); 278 217 } 279 218 280 219 static void ··· 430 369 } 431 370 } 432 371 433 - 434 - static void 435 - _set_image_layout(struct vk_bundle *vk, 436 - VkCommandBuffer cmd_buffer, 437 - VkImage image, 438 - VkAccessFlags src_access_mask, 439 - VkAccessFlags dst_access_mask, 440 - VkImageLayout old_layout, 441 - VkImageLayout new_layout, 442 - VkImageSubresourceRange subresource_range) 443 - { 444 - VkImageMemoryBarrier barrier = { 445 - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 446 - .srcAccessMask = src_access_mask, 447 - .dstAccessMask = dst_access_mask, 448 - .oldLayout = old_layout, 449 - .newLayout = new_layout, 450 - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 451 - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 452 - .image = image, 453 - .subresourceRange = subresource_range, 454 - }; 455 - 456 - vk->vkCmdPipelineBarrier(cmd_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 457 - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 458 - 0, NULL, 1, &barrier); 459 - } 460 - 461 - static void 462 - renderer_init_dummy_images(struct comp_renderer *r) 463 - { 464 - struct vk_bundle *vk = &r->c->vk; 465 - VkCommandBuffer cmd_buffer; 466 - if (vk_init_cmd_buffer(vk, &cmd_buffer) != VK_SUCCESS) 467 - return; 468 - 469 - VkImageSubresourceRange subresource_range = { 470 - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 471 - .baseMipLevel = 0, 472 - .levelCount = 1, 473 - .baseArrayLayer = 0, 474 - .layerCount = 1}; 475 - 476 - VkClearColorValue color = {.float32 = {0.3, 0.3, 0.3, 1}}; 477 - VkExtent2D extent = {.width = 640, .height = 800}; 478 - 479 - VkImageUsageFlags usage = 480 - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 481 - 482 - for (uint32_t i = 0; i < 2; i++) { 483 - vk_create_image_simple( 484 - &r->c->vk, extent, VK_FORMAT_B8G8R8A8_SRGB, usage, 485 - &r->dummy_images[i].memory, &r->dummy_images[i].image); 486 - 487 - _set_image_layout( 488 - vk, cmd_buffer, r->dummy_images[i].image, 0, 489 - VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, 490 - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range); 491 - 492 - vk->vkCmdClearColorImage(cmd_buffer, r->dummy_images[i].image, 493 - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 494 - &color, 1, &subresource_range); 495 - 496 - vk_set_image_layout(vk, cmd_buffer, r->dummy_images[i].image, 497 - VK_ACCESS_TRANSFER_WRITE_BIT, 498 - VK_ACCESS_SHADER_READ_BIT, 499 - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 500 - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 501 - subresource_range); 502 - 503 - vk_create_sampler(vk, &r->dummy_images[i].sampler); 504 - vk_create_view(vk, r->dummy_images[i].image, 505 - VK_FORMAT_B8G8R8A8_SRGB, subresource_range, 506 - &r->dummy_images[i].views[0]); 507 - } 508 - 509 - vk_submit_cmd_buffer(vk, cmd_buffer); 510 - } 511 - 512 372 static void 513 373 _create_fences(struct comp_renderer *r) 514 374 { ··· 531 391 } 532 392 533 393 static void 534 - _set_dummy_images(struct comp_renderer *r) 394 + _get_view_projection(struct comp_renderer *r) 535 395 { 536 - for (uint32_t i = 0; i < 2; i++) 537 - comp_distortion_update_descriptor_set( 538 - r->distortion, r->dummy_images[i].sampler, 539 - r->dummy_images[i].views[0], i, false); 396 + struct xrt_space_relation relation; 397 + uint64_t out_timestamp; 398 + 399 + xrt_device_get_tracked_pose(r->c->xdev, XRT_INPUT_GENERIC_HEAD_POSE, 400 + r->c->last_frame_time_ns, &out_timestamp, 401 + &relation); 402 + 403 + struct xrt_vec3 eye_relation = { 404 + 0.063000f, /* TODO: get actual ipd_meters */ 405 + 0.0f, 406 + 0.0f, 407 + }; 408 + 409 + struct xrt_pose base_space_pose = { 410 + .position = (struct xrt_vec3){0, 0, 0}, 411 + .orientation = (struct xrt_quat){0, 0, 0, 1}, 412 + }; 413 + 414 + for (uint32_t i = 0; i < 2; i++) { 415 + struct xrt_fov fov = r->c->xdev->hmd->views[i].fov; 416 + 417 + comp_layer_renderer_set_fov(r->lr, &fov, i); 418 + 419 + struct xrt_pose view_pose; 420 + xrt_device_get_view_pose(r->c->xdev, &eye_relation, i, 421 + &view_pose); 422 + 423 + struct xrt_pose pose; 424 + math_pose_openxr_locate(&view_pose, &relation.pose, 425 + &base_space_pose, &pose); 426 + 427 + comp_layer_renderer_set_pose(r->lr, &pose, i); 428 + } 540 429 } 541 430 542 431 static void ··· 557 446 _create_fences(r); 558 447 renderer_create_frame_buffers(r); 559 448 renderer_allocate_command_buffers(r); 560 - 561 - renderer_init_dummy_images(r); 562 449 563 450 renderer_init_descriptor_pool(r); 564 451 ··· 569 456 r->c->xdev->hmd, r->descriptor_pool, 570 457 r->settings->flip_y); 571 458 572 - _set_dummy_images(r); 459 + VkExtent2D extent = { 460 + .width = r->c->xdev->hmd->screens[0].w_pixels, 461 + .height = r->c->xdev->hmd->screens[0].h_pixels, 462 + }; 463 + 464 + r->lr = comp_layer_renderer_create(vk, extent, VK_FORMAT_B8G8R8A8_SRGB); 465 + 466 + for (uint32_t i = 0; i < 2; i++) { 467 + comp_distortion_update_descriptor_set( 468 + r->distortion, r->lr->framebuffers[i].sampler, 469 + r->lr->framebuffers[i].view, i, false); 470 + } 573 471 574 472 renderer_build_command_buffers(r); 575 473 } 576 474 577 475 void 578 - comp_renderer_set_idle_images(struct comp_renderer *r) 476 + comp_renderer_set_quad_layer(struct comp_renderer *r, 477 + struct comp_swapchain_image *image, 478 + struct xrt_pose *pose, 479 + struct xrt_vec2 *size, 480 + bool flip_y, 481 + uint32_t layer) 579 482 { 580 - _set_dummy_images(r); 581 - renderer_rebuild_command_buffers(r); 483 + comp_layer_update_descriptors(r->lr->layers[layer], image->sampler, 484 + image->views[0]); 485 + 486 + struct xrt_matrix_4x4 model_matrix; 487 + math_matrix_4x4_quad_model(pose, size, &model_matrix); 488 + 489 + comp_layer_set_model_matrix(r->lr->layers[layer], &model_matrix); 490 + 491 + r->lr->layers[layer]->type = COMP_LAYER_QUAD; 492 + comp_layer_set_flip_y(r->lr->layers[layer], flip_y); 493 + 494 + r->c->vk.vkDeviceWaitIdle(r->c->vk.device); 582 495 } 583 496 584 - static void 585 - renderer_set_swapchain_image(struct comp_renderer *r, 586 - uint32_t eye, 587 - struct comp_swapchain_image *image, 588 - uint32_t layer, 589 - bool flip_y) 497 + void 498 + comp_renderer_set_projection_layer(struct comp_renderer *r, 499 + struct comp_swapchain_image *left_image, 500 + struct comp_swapchain_image *right_image, 501 + bool flip_y, 502 + uint32_t layer) 590 503 { 591 - if (eye > 1) { 592 - COMP_ERROR(r->c, "Swapchain image %p %u not found", 593 - (void *)image, eye); 594 - return; 595 - } 504 + comp_layer_update_stereo_descriptors( 505 + r->lr->layers[layer], left_image->sampler, right_image->sampler, 506 + left_image->views[0], right_image->views[0]); 596 507 597 - if (!r->one_buffer_imported[eye]) { 598 - COMP_DEBUG(r->c, 599 - "Updating descriptor set for" 600 - " swapchain image %p and eye %u", 601 - (void *)image, eye); 602 - comp_distortion_update_descriptor_set( 603 - r->distortion, image->sampler, image->views[layer], 604 - (uint32_t)eye, flip_y); 605 - renderer_rebuild_command_buffers(r); 606 - r->one_buffer_imported[eye] = true; 607 - } 508 + comp_layer_set_flip_y(r->lr->layers[layer], flip_y); 509 + 510 + r->lr->layers[layer]->type = COMP_LAYER_STEREO_PROJECTION; 608 511 } 609 512 610 - static void 611 - renderer_render(struct comp_renderer *r) 513 + void 514 + comp_renderer_draw(struct comp_renderer *r) 612 515 { 516 + _get_view_projection(r); 517 + comp_layer_renderer_draw(r->lr); 518 + r->c->vk.vkDeviceWaitIdle(r->c->vk.device); 519 + 613 520 r->c->window->flush(r->c->window); 614 521 renderer_acquire_swapchain_image(r); 615 522 renderer_submit_queue(r); ··· 898 805 r->distortion = NULL; 899 806 } 900 807 901 - // Dummy images 902 - for (uint32_t i = 0; i < 2; i++) { 903 - comp_swapchain_image_cleanup(vk, 1, &r->dummy_images[i]); 904 - } 905 - 906 808 // Discriptor pool 907 809 if (r->descriptor_pool != VK_NULL_HANDLE) { 908 810 vk->vkDestroyDescriptorPool(vk->device, r->descriptor_pool, ··· 956 858 r->semaphores.render_complete, NULL); 957 859 r->semaphores.render_complete = VK_NULL_HANDLE; 958 860 } 861 + 862 + comp_layer_renderer_destroy(r->lr); 863 + } 864 + 865 + void 866 + comp_renderer_allocate_layers(struct comp_renderer *self, uint32_t num_layers) 867 + { 868 + comp_layer_renderer_allocate_layers(self->lr, num_layers); 869 + } 870 + 871 + void 872 + comp_renderer_destroy_layers(struct comp_renderer *self) 873 + { 874 + comp_layer_renderer_destroy_layers(self->lr); 959 875 }
+23 -22
src/xrt/compositor/main/comp_renderer.h
··· 11 11 #pragma once 12 12 13 13 #include "xrt/xrt_compiler.h" 14 + #include "xrt/xrt_defines.h" 14 15 15 16 #ifdef __cplusplus 16 17 extern "C" { ··· 30 31 comp_renderer_create(struct comp_compositor *c); 31 32 32 33 /*! 33 - * Render a distorted stereo frame. 34 - * 35 - * @ingroup comp_main 36 - */ 37 - void 38 - comp_renderer_frame(struct comp_renderer *r, 39 - struct comp_swapchain_image *left, 40 - uint32_t left_layer, 41 - struct comp_swapchain_image *right, 42 - uint32_t right_layer, 43 - bool flip_y); 44 - 45 - /*! 46 34 * Reset renderer as input has changed. 47 35 * 48 36 * @ingroup comp_main 49 37 */ 50 - 51 38 void 52 39 comp_renderer_reset(struct comp_renderer *r); 53 40 ··· 60 47 comp_renderer_destroy(struct comp_renderer *r); 61 48 62 49 /*! 63 - * Set dummy images in renderer. 50 + * Render frame. 64 51 * 65 52 * @ingroup comp_main 66 53 */ 67 54 void 68 - comp_renderer_set_idle_images(struct comp_renderer *r); 55 + comp_renderer_draw(struct comp_renderer *r); 56 + 57 + void 58 + comp_renderer_set_projection_layer(struct comp_renderer *r, 59 + struct comp_swapchain_image *left_image, 60 + struct comp_swapchain_image *right_image, 61 + bool flip_y, 62 + uint32_t layer); 69 63 70 - /*! 71 - * Render frame without setting new images. 72 - * 73 - * @ingroup comp_main 74 - */ 75 64 void 76 - comp_renderer_frame_cached(struct comp_renderer *r); 65 + comp_renderer_set_quad_layer(struct comp_renderer *r, 66 + struct comp_swapchain_image *image, 67 + struct xrt_pose *pose, 68 + struct xrt_vec2 *size, 69 + bool flip_y, 70 + uint32_t layer); 71 + 72 + 73 + void 74 + comp_renderer_allocate_layers(struct comp_renderer *self, uint32_t num_layers); 75 + 76 + void 77 + comp_renderer_destroy_layers(struct comp_renderer *self); 77 78 78 79 #ifdef __cplusplus 79 80 }
+34 -5
src/xrt/ipc/ipc_server.h
··· 14 14 15 15 #include "os/os_threading.h" 16 16 17 + #include "ipc_protocol.h" 18 + 17 19 #include <stdio.h> 18 20 19 21 #ifdef __cplusplus ··· 81 83 uint32_t num_images; 82 84 }; 83 85 86 + struct ipc_quad_render_state 87 + { 88 + uint32_t swapchain_index; 89 + uint32_t image_index; 90 + 91 + struct xrt_pose pose; 92 + struct xrt_vec2 size; 93 + }; 94 + 95 + struct ipc_stereo_projection_render_state 96 + { 97 + struct 98 + { 99 + uint32_t swapchain_index; 100 + uint32_t image_index; 101 + } l, r; 102 + }; 103 + 104 + struct ipc_layer_render_state 105 + { 106 + enum ipc_layer_type type; 107 + bool flip_y; 108 + 109 + union { 110 + struct ipc_quad_render_state quad; 111 + struct ipc_stereo_projection_render_state stereo; 112 + }; 113 + }; 114 + 84 115 /*! 85 116 * Render state for a client. 86 117 * ··· 89 120 struct ipc_render_state 90 121 { 91 122 bool rendering; 92 - bool flip_y; 93 - uint32_t l_swapchain_index; 94 - uint32_t l_image_index; 95 - uint32_t r_swapchain_index; 96 - uint32_t r_image_index; 123 + enum xrt_blend_mode env_blend_mode; 124 + uint32_t num_layers; 125 + struct ipc_layer_render_state layers[IPC_MAX_LAYERS]; 97 126 }; 98 127 99 128 /*!
+42 -12
src/xrt/ipc/ipc_server_client.c
··· 101 101 { 102 102 struct ipc_shared_memory *ism = cs->server->ism; 103 103 struct ipc_layer_slot *slot = &ism->slots[slot_id]; 104 - struct ipc_layer_entry *layer = &slot->layers[0]; 105 - struct ipc_layer_stereo_projection *stereo = &layer->stereo; 104 + 105 + for (uint32_t i = 0; i < slot->num_layers; i++) { 106 + cs->render_state.layers[i].type = slot->layers[i].type; 107 + 108 + struct ipc_layer_entry *sl = &slot->layers[i]; 109 + volatile struct ipc_layer_render_state *rl = 110 + &cs->render_state.layers[i]; 111 + 112 + rl->flip_y = sl->flip_y; 113 + 114 + switch (slot->layers[i].type) { 115 + case IPC_LAYER_STEREO_PROJECTION: 116 + rl->stereo.l.swapchain_index = 117 + sl->stereo.l.swapchain_id; 118 + rl->stereo.l.image_index = sl->stereo.l.image_index; 119 + rl->stereo.r.swapchain_index = 120 + sl->stereo.r.swapchain_id; 121 + rl->stereo.r.image_index = sl->stereo.r.image_index; 122 + break; 123 + case IPC_LAYER_QUAD: 124 + rl->quad.swapchain_index = sl->quad.swapchain_id; 125 + rl->quad.image_index = sl->quad.image_index; 126 + rl->quad.pose = sl->quad.pose; 127 + rl->quad.size = sl->quad.size; 128 + break; 129 + } 130 + } 106 131 107 - cs->render_state.flip_y = layer->flip_y; 108 - cs->render_state.l_swapchain_index = stereo->l.swapchain_id; 109 - cs->render_state.l_image_index = stereo->l.image_index; 110 - cs->render_state.r_swapchain_index = stereo->r.swapchain_id; 111 - cs->render_state.r_image_index = stereo->r.image_index; 132 + cs->render_state.num_layers = slot->num_layers; 112 133 cs->render_state.rendering = true; 113 134 114 135 *out_free_slot_id = (slot_id + 1) % IPC_MAX_SLOTS; ··· 415 436 cs->num_swapchains = 0; 416 437 417 438 // Make sure to reset the renderstate fully. 418 - cs->render_state.flip_y = false; 419 - cs->render_state.l_swapchain_index = 0; 420 - cs->render_state.l_image_index = 0; 421 - cs->render_state.r_swapchain_index = 0; 422 - cs->render_state.r_image_index = 0; 439 + cs->render_state.num_layers = 0; 423 440 cs->render_state.rendering = false; 441 + for (uint32_t i = 0; i < ARRAY_SIZE(cs->render_state.layers); ++i) { 442 + volatile struct ipc_layer_render_state *rl = 443 + &cs->render_state.layers[i]; 424 444 445 + rl->flip_y = false; 446 + rl->stereo.l.swapchain_index = 0; 447 + rl->stereo.l.image_index = 0; 448 + rl->stereo.r.swapchain_index = 0; 449 + rl->stereo.r.image_index = 0; 450 + rl->quad.swapchain_index = 0; 451 + rl->quad.image_index = 0; 452 + } 453 + 454 + // Destroy all swapchains now. 425 455 for (uint32_t j = 0; j < IPC_MAX_CLIENT_SWAPCHAINS; j++) { 426 456 xrt_swapchain_destroy((struct xrt_swapchain **)&cs->xscs[j]); 427 457 cs->swapchain_handles[j] = -1;
+77 -56
src/xrt/ipc/ipc_server_process.c
··· 515 515 } 516 516 517 517 static void 518 - set_rendering_state(volatile struct ipc_client_state *active_client, 519 - struct comp_swapchain_image **l, 520 - struct comp_swapchain_image **r, 521 - bool *using_idle_images, 522 - bool *flip_y) 518 + _update_projection_layer(struct comp_compositor *c, 519 + volatile struct ipc_client_state *active_client, 520 + volatile struct ipc_layer_render_state *layer, 521 + uint32_t i) 522 + { 523 + uint32_t lsi = layer->stereo.l.swapchain_index; 524 + uint32_t rsi = layer->stereo.r.swapchain_index; 525 + struct comp_swapchain *cl = comp_swapchain(active_client->xscs[lsi]); 526 + struct comp_swapchain *cr = comp_swapchain(active_client->xscs[rsi]); 527 + 528 + struct comp_swapchain_image *l = NULL; 529 + struct comp_swapchain_image *r = NULL; 530 + l = &cl->images[layer->stereo.l.image_index]; 531 + r = &cr->images[layer->stereo.r.image_index]; 532 + 533 + comp_renderer_set_projection_layer(c->r, l, r, layer->flip_y, i); 534 + } 535 + 536 + static void 537 + _update_quad_layer(struct comp_compositor *c, 538 + volatile struct ipc_client_state *active_client, 539 + volatile struct ipc_layer_render_state *layer, 540 + uint32_t i) 541 + { 542 + uint32_t sci = layer->quad.swapchain_index; 543 + struct comp_swapchain *sc = comp_swapchain(active_client->xscs[sci]); 544 + struct comp_swapchain_image *image = NULL; 545 + image = &sc->images[layer->quad.image_index]; 546 + 547 + struct xrt_pose pose = layer->quad.pose; 548 + struct xrt_vec2 size = layer->quad.size; 549 + 550 + comp_renderer_set_quad_layer(c->r, image, &pose, &size, layer->flip_y, 551 + i); 552 + } 553 + 554 + static void 555 + _update_layers(struct comp_compositor *c, 556 + volatile struct ipc_client_state *active_client, 557 + uint32_t *num_layers) 523 558 { 524 - // our ipc server thread will fill in l & r 525 - // swapchain indices and toggle wait to false 526 - // when the client calls end_frame, signalling 527 - // us to render. 528 559 volatile struct ipc_render_state *render_state = 529 560 &active_client->render_state; 530 561 531 - if (!render_state->rendering) { 532 - return; 562 + if (*num_layers != render_state->num_layers) { 563 + // TODO: Resizing here would be faster 564 + *num_layers = render_state->num_layers; 565 + comp_renderer_destroy_layers(c->r); 566 + comp_renderer_allocate_layers(c->r, render_state->num_layers); 533 567 } 534 568 535 - uint32_t li = render_state->l_swapchain_index; 536 - uint32_t ri = render_state->r_swapchain_index; 537 - struct comp_swapchain *cl = comp_swapchain(active_client->xscs[li]); 538 - struct comp_swapchain *cr = comp_swapchain(active_client->xscs[ri]); 539 - *l = &cl->images[render_state->l_image_index]; 540 - *r = &cr->images[render_state->r_image_index]; 541 - *flip_y = render_state->flip_y; 542 - 543 - // set our client state back to waiting. 544 - render_state->rendering = false; 545 - 546 - // comp_compositor_garbage_collect(c); 547 - 548 - *using_idle_images = false; 569 + for (uint32_t i = 0; i < render_state->num_layers; i++) { 570 + volatile struct ipc_layer_render_state *layer = 571 + &render_state->layers[i]; 572 + switch (layer->type) { 573 + case IPC_LAYER_STEREO_PROJECTION: { 574 + _update_projection_layer(c, active_client, layer, i); 575 + break; 576 + } 577 + case IPC_LAYER_QUAD: { 578 + _update_quad_layer(c, active_client, layer, i); 579 + break; 580 + } 581 + } 582 + } 549 583 } 550 584 551 585 static int ··· 559 593 vs->thread_state.server = vs; 560 594 vs->thread_state.xc = xc; 561 595 562 - struct comp_swapchain_image *last_l = NULL; 563 - struct comp_swapchain_image *last_r = NULL; 564 - 565 - bool using_idle_images = true; 596 + uint32_t num_layers = 0; 566 597 567 598 while (vs->running) { 568 599 ··· 570 601 * Check polling. 571 602 */ 572 603 check_epoll(vs); 573 - 574 604 575 605 /* 576 606 * Update active client. ··· 581 611 active_client = &vs->thread_state; 582 612 } 583 613 584 - 585 614 /* 586 615 * Render the swapchains. 587 616 */ 588 617 589 - struct comp_swapchain_image *l = NULL; 590 - struct comp_swapchain_image *r = NULL; 591 - bool flip_y = false; 592 - 593 618 if (active_client == NULL || !active_client->active || 594 619 active_client->num_swapchains == 0) { 595 - if (!using_idle_images) { 596 - COMP_DEBUG(c, "Resetting to idle images."); 597 - comp_renderer_reset(c->r); 598 - comp_renderer_set_idle_images(c->r); 599 - using_idle_images = true; 600 - last_l = NULL; 601 - last_r = NULL; 620 + if (num_layers != 0) { 621 + COMP_DEBUG(c, "Destroying layers."); 622 + comp_renderer_destroy_layers(c->r); 623 + num_layers = 0; 602 624 } 603 625 } else { 604 - set_rendering_state(active_client, &l, &r, 605 - &using_idle_images, &flip_y); 606 - } 626 + // our ipc server thread will fill in l & r 627 + // swapchain indices and toggle wait to false 628 + // when the client calls end_frame, signalling 629 + // us to render. 630 + volatile struct ipc_render_state *render_state = 631 + &active_client->render_state; 632 + 633 + if (render_state->rendering) { 634 + _update_layers(c, active_client, &num_layers); 607 635 608 - // Render the idle images or already cached images state. 609 - if ((l == NULL || r == NULL) || (l == last_l && r == last_r)) { 610 - comp_renderer_frame_cached(c->r); 611 - comp_compositor_garbage_collect(c); 612 - continue; 636 + // set our client state back to waiting. 637 + render_state->rendering = false; 638 + } 613 639 } 614 640 615 - // Rebuild command buffers if we are showing new buffers. 616 - comp_renderer_reset(c->r); 617 - comp_renderer_frame(c->r, l, 0, r, 0, flip_y); 618 - 619 - last_l = l; 620 - last_r = r; 641 + comp_renderer_draw(c->r); 621 642 622 643 // Now is a good time to destroy objects. 623 644 comp_compositor_garbage_collect(c);