Esempio n. 1
0
void set_up_vertex_buffer(struct ft2_source *srcdata)
{
	FT_UInt glyph_index = 0;
	uint32_t x = 0, space_pos = 0, word_width = 0;
	size_t len;

	if (!srcdata->text)
		return;

	if (srcdata->custom_width >= 100)
		srcdata->cx = srcdata->custom_width;
	else
		srcdata->cx = get_ft2_text_width(srcdata->text, srcdata);
	srcdata->cy = srcdata->max_h;

	obs_enter_graphics();
	if (srcdata->vbuf != NULL) {
		gs_vertbuffer_t *tmpvbuf = srcdata->vbuf;
		srcdata->vbuf = NULL;
		gs_vertexbuffer_destroy(tmpvbuf);
	}
	srcdata->vbuf = create_uv_vbuffer((uint32_t)wcslen(srcdata->text) * 6,
			true);

	if (srcdata->custom_width <= 100) goto skip_word_wrap;
	if (!srcdata->word_wrap) goto skip_word_wrap;

	len = wcslen(srcdata->text);

	for (uint32_t i = 0; i <= len; i++) {
		if (i == wcslen(srcdata->text)) goto eos_check;

		if (srcdata->text[i] != L' ' && srcdata->text[i] != L'\n')
			goto next_char;

	eos_check:;
		if (x + word_width > srcdata->custom_width) {
			if (space_pos != 0)
				srcdata->text[space_pos] = L'\n';
			x = 0;
		}
		if (i == wcslen(srcdata->text)) goto eos_skip;

		x += word_width;
		word_width = 0;
		if (srcdata->text[i] == L'\n')
			x = 0;
		if (srcdata->text[i] == L' ')
			space_pos = i;
	next_char:;
		glyph_index = FT_Get_Char_Index(srcdata->font_face,
			srcdata->text[i]);
		word_width += src_glyph->xadv;
	eos_skip:;
	}

skip_word_wrap:;
	fill_vertex_buffer(srcdata);
	obs_leave_graphics();
}
Esempio n. 2
0
static void before_present(VkQueue queue, layer_data *my_data, SwapChainData *swapChain, unsigned imageIndex) {
    VkLayerDispatchTable *pTable = my_data->device_dispatch_table;

    if (!my_data->fontUploadComplete) {
        VkSubmitInfo si = {};
        si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
        si.pNext = nullptr;
        si.waitSemaphoreCount = 0;
        si.commandBufferCount = 1;
        si.signalSemaphoreCount = 0;
        si.pCommandBuffers = &my_data->fontUploadCmdBuffer;

        pTable->QueueSubmit(queue, 1, &si, VK_NULL_HANDLE);
        my_data->fontUploadComplete = true;
#ifdef OVERLAY_DEBUG
        printf("Font image layout transition queued\n");
#endif
    }

    WsiImageData *id = swapChain->presentableImages[imageIndex];

    /* update the overlay content */

    vertex *vertices = nullptr;

    /* guaranteed not in flight due to WSI surface being available */
    VkResult U_ASSERT_ONLY err =
        pTable->MapMemory(my_data->dev, id->vertexBufferMemory, 0, id->vertexBufferSize, 0, (void **)&vertices);
    assert(!err);

    /* write vertices for string in here */
    id->numVertices = fill_vertex_buffer(my_data, vertices, imageIndex);

    pTable->UnmapMemory(my_data->dev, id->vertexBufferMemory);

    /* JIT record a command buffer to draw the overlay */

    VkCommandBufferBeginInfo cbbi;
    cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    cbbi.pNext = nullptr;
    cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    cbbi.pInheritanceInfo = nullptr;

    VkImageMemoryBarrier imb;
    imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    imb.pNext = nullptr;
    imb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
    imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    imb.image = id->image;
    imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    imb.subresourceRange.baseMipLevel = 0;
    imb.subresourceRange.levelCount = 1;
    imb.subresourceRange.baseArrayLayer = 0;
    imb.subresourceRange.layerCount = 1;
    imb.srcQueueFamilyIndex = my_data->graphicsQueueFamilyIndex;
    imb.dstQueueFamilyIndex = my_data->graphicsQueueFamilyIndex;

    VkRenderPassBeginInfo rpbi;
    rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    rpbi.pNext = nullptr;
    rpbi.renderPass = swapChain->render_pass;
    rpbi.framebuffer = id->framebuffer;
    rpbi.renderArea.offset.x = 0;
    rpbi.renderArea.offset.y = 0;
    rpbi.renderArea.extent.width = swapChain->width;
    rpbi.renderArea.extent.height = swapChain->height;
    rpbi.clearValueCount = 0;
    rpbi.pClearValues = nullptr;

    pTable->BeginCommandBuffer(id->cmd, &cbbi);
    pTable->CmdPipelineBarrier(id->cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                               0 /* dependency flags */, 0, nullptr, /* memory barriers */
                               0, nullptr,                           /* buffer memory barriers */
                               1, &imb);                             /* image memory barriers */
    pTable->CmdBeginRenderPass(id->cmd, &rpbi, VK_SUBPASS_CONTENTS_INLINE);

    pTable->CmdBindPipeline(id->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, swapChain->pipeline);
    pTable->CmdBindDescriptorSets(id->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, my_data->pl, 0, 1, &my_data->desc_set, 0, nullptr);

    VkDeviceSize offsets[] = {0};
    VkBuffer buffers[] = {id->vertexBuffer};

    pTable->CmdBindVertexBuffers(id->cmd, 0, 1, buffers, offsets);

    pTable->CmdDraw(id->cmd, id->numVertices, 1, 0, 0);

    pTable->CmdEndRenderPass(id->cmd);
    pTable->EndCommandBuffer(id->cmd);

    /* Schedule this command buffer for execution. TODO: Do we need to protect
     * ourselves from an app that didn't wait for the presentation image to
     * be idle before mangling it? If the app is well-behaved, our command
     * buffer is guaranteed to have been retired before the app tries to
     * present it again.
     */
    VkSubmitInfo si = {};
    si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    si.pNext = nullptr;
    si.waitSemaphoreCount = 0;
    si.commandBufferCount = 1;
    si.signalSemaphoreCount = 0;
    si.pCommandBuffers = &id->cmd;
    pTable->WaitForFences(my_data->dev, 1, &my_data->fence, VK_TRUE, UINT64_MAX);
    pTable->ResetFences(my_data->dev, 1, &my_data->fence);
    pTable->QueueSubmit(queue, 1, &si, my_data->fence);

    /* Reset per-frame stats */
    my_data->cmdBuffersThisFrame = 0;
}
Esempio n. 3
0
static void before_present(VkQueue queue, layer_data *my_data,
                           SwapChainData *swapChain, unsigned imageIndex) {
    VkLayerDispatchTable *pTable = my_data->device_dispatch_table;

    if (!my_data->fontUploadComplete) {
        VkSubmitInfo si;
        si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
        si.pNext = nullptr;
        si.waitSemaphoreCount = 0;
        si.commandBufferCount = 1;
        si.signalSemaphoreCount = 0;
        si.pCommandBuffers = &my_data->fontUploadCmdBuffer;

        pTable->QueueSubmit(queue, 1, &si, VK_NULL_HANDLE);
        my_data->fontUploadComplete = true;
#ifdef OVERLAY_DEBUG
        printf("Font image layout transition queued\n");
#endif
    }

    WsiImageData *id = swapChain->presentableImages[imageIndex];

    /* update the overlay content */

    vertex *vertices = nullptr;

    /* guaranteed not in flight due to WSI surface being available */
    VkResult U_ASSERT_ONLY err =
        pTable->MapMemory(my_data->dev, id->vertexBufferMemory, 0,
                          id->vertexBufferSize, 0, (void **)&vertices);
    assert(!err);

    /* write vertices for string in here */
    id->numVertices = fill_vertex_buffer(my_data, vertices, imageIndex);

    pTable->UnmapMemory(my_data->dev, id->vertexBufferMemory);

    /* JIT record a command buffer to draw the overlay */

    VkCommandBufferBeginInfo cbbi;
    cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    cbbi.pNext = nullptr;
    cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    cbbi.pInheritanceInfo = nullptr;

    VkRenderPassBeginInfo rpbi;
    rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    rpbi.pNext = nullptr;
    rpbi.renderPass = swapChain->render_pass;
    rpbi.framebuffer = id->framebuffer;
    rpbi.renderArea.offset.x = 0;
    rpbi.renderArea.offset.y = 0;
    rpbi.renderArea.extent.width = swapChain->width;
    rpbi.renderArea.extent.height = swapChain->height;
    rpbi.clearValueCount = 0;
    rpbi.pClearValues = nullptr;

    pTable->BeginCommandBuffer(id->cmd, &cbbi);
    pTable->CmdBeginRenderPass(id->cmd, &rpbi, VK_SUBPASS_CONTENTS_INLINE);

    pTable->CmdBindPipeline(id->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
                            swapChain->pipeline);
    pTable->CmdBindDescriptorSets(id->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
                                  my_data->pl, 0, 1, &my_data->desc_set, 0,
                                  nullptr);

    VkDeviceSize offsets[] = {0};
    VkBuffer buffers[] = {id->vertexBuffer};

    pTable->CmdBindVertexBuffers(id->cmd, 0, 1, buffers, offsets);

    pTable->CmdDraw(id->cmd, id->numVertices, 1, 0, 0);

    pTable->CmdEndRenderPass(id->cmd);
    pTable->EndCommandBuffer(id->cmd);

    /* Schedule this command buffer for execution. TODO: Do we need to protect
     * ourselves from an app that didn't wait for the presentation image to
     * be idle before mangling it? If the app is well-behaved, our command
     * buffer is guaranteed to have been retired before the app tries to
     * present it again.
     */
    VkFence null_fence = VK_NULL_HANDLE;
    VkSubmitInfo si;
    si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    si.pNext = nullptr;
    si.waitSemaphoreCount = 0;
    si.commandBufferCount = 1;
    si.signalSemaphoreCount = 0;
    si.pCommandBuffers = &id->cmd;
    pTable->QueueSubmit(queue, 1, &si, null_fence);

    /* Reset per-frame stats */
    my_data->cmdBuffersThisFrame = 0;
}