blob: 9aefeaaf72c621204bcf6abe85328865ee45f2f8 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_UI_LIB_ESCHER_UTIL_IMAGE_UTILS_H_
#define SRC_UI_LIB_ESCHER_UTIL_IMAGE_UTILS_H_
#ifdef __Fuchsia__
#include <lib/fit/function.h>
#endif
#include <utility>
#include "src/ui/lib/escher/escher.h"
#include "src/ui/lib/escher/forward_declarations.h"
#include "src/ui/lib/escher/vk/image.h"
namespace escher {
class BatchGpuUploader;
class ImageFactory;
namespace image_utils {
using ImageConversionFunction = fit::function<void(void*, const void*, uint32_t, uint32_t)>;
// Returns the number of bytes per pixel for the given format.
size_t BytesPerPixel(vk::Format format);
// Return true if |format| can be used as a depth buffer.
bool IsDepthFormat(vk::Format format);
// Return true if |format| can be used as a stencil buffer.
bool IsStencilFormat(vk::Format format);
// Return true is |format| is one of the formats that Escher can treat as a YUV format.
// Currently these include:
// - eG8B8G8R8422Unorm
// - eG8B8R82Plane420Unorm
// TODO(fxbug.dev/24595): use of these formats is not enough to assume NV12, but they're currently
// the only formats we support at the sampler level.
bool IsYuvFormat(vk::Format format);
// Return a pair of booleans, each of which is true if |format| can be used as
// a depth or stencil buffer, respectively.
std::pair<bool, bool> IsDepthStencilFormat(vk::Format format);
// If |format| is a depth-stencil format, return the appropriate combination
// of eDepth and eStencil bits. Otherwise, treat it as a color format, and
// return eColor.
vk::ImageAspectFlags FormatToColorOrDepthStencilAspectFlags(vk::Format format);
vk::ImageCreateInfo CreateVkImageCreateInfo(const ImageInfo& info, vk::ImageLayout initial_layout);
// Helper function that creates a VkImage given the parameters in ImageInfo.
// This does not bind the VkImage to memory; the caller must do that
// separately after calling this function.
vk::Image CreateVkImage(const vk::Device& device, const ImageInfo& info,
vk::ImageLayout initial_layout);
// Return a new Image that is suitable for use as a depth attachment.
// |image_factory| is a generic interface that could be an Image cache (in which
// case a new Image might be created, or an existing one reused). Alternatively
// the factory could allocate a new Image every time.
ImagePtr NewDepthImage(ImageFactory* image_factory, vk::Format format, uint32_t width,
uint32_t height, vk::ImageUsageFlags additional_flags);
// Return a new Image that is suitable for use as a color attachment.
// |image_factory| is a generic interface that could be an Image cache (in which
// case a new Image might be created, or an existing one reused). Alternatively
// the factory could allocate a new Image every time.
ImagePtr NewColorAttachmentImage(ImageFactory* image_factory, uint32_t width, uint32_t height,
vk::ImageUsageFlags additional_flags);
// Returns new image bound to the provided gpu memory, with the specified create info. This
// should only be called in a scenario where we know the |gpu_mem| buffer passed in will be
// compatible with the Vulkan image memory requirements such as being of a sufficiently large
// size to back the image. Otherwise, this function returns nullptr.
ImagePtr NewImage(const vk::Device& device, const vk::ImageCreateInfo& create_info,
escher::GpuMemPtr gpu_mem, escher::ResourceRecycler* resource_recycler);
// Return new Image containing the provided pixels. Uses transfer queue to
// efficiently transfer image data to GPU.
// |image_factory| is a generic interface that could be an Image cache (in which
// case a new Image might be created, or an existing one reused). Alternatively
// the factory could allocate a new Image every time.
ImagePtr NewImage(ImageFactory* image_factory, vk::Format format, uint32_t width, uint32_t height,
vk::ImageUsageFlags additional_flags = vk::ImageUsageFlags(),
vk::MemoryPropertyFlags memory_flags = vk::MemoryPropertyFlags());
// Write the contents of |pixels| into an existing |gpu_image|.
// The width, and height of |pixels| is assumed to match that of
// |gpu_image|.
// If the format of |pixels| is different from |gpu_image|, a conversion
// function that can convert from |pixels| to |gpu_image| should be
// provided as |convertion_func|.
// Note that all escher images are stored in GPU memory. The use of gpu_image
// here is to specifically differentiate it from pixels, which may be stored in
// host_memory.
void WritePixelsToImage(
escher::BatchGpuUploader* batch_gpu_uploader, const uint8_t* pixels, const ImagePtr& gpu_image,
vk::ImageLayout final_layout = vk::ImageLayout::eShaderReadOnlyOptimal,
const escher::image_utils::ImageConversionFunction& convertion_func = nullptr);
// Return new Image containing the provided pixels. Uses transfer queue to
// efficiently transfer image data to GPU. If bytes is null, don't bother
// transferring.
// |image_factory| is a generic interface that could be an Image cache (in which
// case a new Image might be created, or an existing one reused). Alternatively
// the factory could allocate a new Image every time.
ImagePtr NewRgbaImage(ImageFactory* image_factory, BatchGpuUploader* gpu_uploader, uint32_t width,
uint32_t height, const uint8_t* bytes,
vk::ImageLayout final_layout = vk::ImageLayout::eShaderReadOnlyOptimal);
// Returns RGBA image.
// |image_factory| is a generic interface that could be an Image cache (in which
// case a new Image might be created, or an existing one reused). Alternatively
// the factory could allocate a new Image every time.
ImagePtr NewCheckerboardImage(ImageFactory* image_factory, BatchGpuUploader* gpu_uploader,
uint32_t width, uint32_t height);
// Returns RGBA image.
// |image_factory| is a generic interface that could be an Image cache (in which
// case a new Image might be created, or an existing one reused). Alternatively
// the factory could allocate a new Image every time.
ImagePtr NewGradientImage(ImageFactory* image_factory, BatchGpuUploader* gpu_uploader,
uint32_t width, uint32_t height);
// Returns single-channel luminance image containing white noise.
// |image_factory| is a generic interface that could be an Image cache (in which
// case a new Image might be created, or an existing one reused). Alternatively
// the factory could allocate a new Image every time.
ImagePtr NewNoiseImage(ImageFactory* image_factory, BatchGpuUploader* gpu_uploader, uint32_t width,
uint32_t height,
vk::ImageUsageFlags additional_flags = vk::ImageUsageFlags());
// Return RGBA pixels containing a checkerboard pattern, where each white/black
// region is a single pixel. Only works for even values of width/height.
std::unique_ptr<uint8_t[]> NewCheckerboardPixels(uint32_t width, uint32_t height,
size_t* out_size = nullptr);
// Return RGBA pixels containing a gradient where the top row is white and the
// bottom row is black. Only works for even values of width/height.
std::unique_ptr<uint8_t[]> NewGradientPixels(uint32_t width, uint32_t height,
size_t* out_size = nullptr);
// Return eR8Unorm pixels containing random noise.
std::unique_ptr<uint8_t[]> NewNoisePixels(uint32_t width, uint32_t height,
size_t* out_size = nullptr);
// Creates a vk::ImageCreateInfo with common default values and |vk_format|.
vk::ImageCreateInfo GetDefaultImageConstraints(const vk::Format& vk_format);
} // namespace image_utils
} // namespace escher
#endif // SRC_UI_LIB_ESCHER_UTIL_IMAGE_UTILS_H_