bool Image::setContentFromBitmap()

in RenderScriptMigrationSample/app/src/main/cpp/VulkanResources.cpp [151:194]


bool Image::setContentFromBitmap(JNIEnv* env, jobject bitmap) {
    // Get bitmap info
    AndroidBitmapInfo info;
    RET_CHECK(AndroidBitmap_getInfo(env, bitmap, &info) == ANDROID_BITMAP_RESULT_SUCCESS);
    RET_CHECK(info.width == mWidth);
    RET_CHECK(info.height == mHeight);
    RET_CHECK(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888);
    RET_CHECK(info.stride % 4 == 0);

    // Allocate a staging buffer
    const uint32_t bufferSize = info.stride * info.height;
    auto stagingBuffer = Buffer::create(
            mContext, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

    // Copy bitmap pixels to the buffer memory
    void* bitmapData = nullptr;
    RET_CHECK(AndroidBitmap_lockPixels(env, bitmap, &bitmapData) == ANDROID_BITMAP_RESULT_SUCCESS);
    const bool success = stagingBuffer->copyFrom(bitmapData);
    AndroidBitmap_unlockPixels(env, bitmap);
    RET_CHECK(success);

    // Set layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to prepare for buffer-image copy
    RET_CHECK(transitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL));

    // Copy buffer to image
    VulkanCommandBuffer copyCommand(mContext->device(), mContext->commandPool());
    RET_CHECK(mContext->beginSingleTimeCommand(copyCommand.pHandle()));
    const VkBufferImageCopy bufferImageCopy = {
            .bufferOffset = 0,
            .bufferRowLength = info.stride / 4,
            .bufferImageHeight = mHeight,
            .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
            .imageOffset = {0, 0, 0},
            .imageExtent = {mWidth, mHeight, 1},
    };
    vkCmdCopyBufferToImage(copyCommand.handle(), stagingBuffer->getBufferHandle(), mImage.handle(),
                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferImageCopy);
    RET_CHECK(mContext->endAndSubmitSingleTimeCommand(copyCommand.handle()));

    // Set layout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL to prepare for input sampler usage
    RET_CHECK(transitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
    return true;
}