blob: 2f3b02674f47bf7d90f29611f494224d998eb110 [file] [log] [blame]
// Copyright 2020 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_SCENIC_LIB_FLATLAND_RENDERER_RENDERER_H_
#define SRC_UI_SCENIC_LIB_FLATLAND_RENDERER_RENDERER_H_
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/zx/event.h>
#include <optional>
// clang-format off
#include "src/ui/lib/glm_workaround/glm_workaround.h"
// clang-format on
#include <glm/mat3x3.hpp>
#include <glm/vec2.hpp>
#include <glm/vec4.hpp>
#include "src/ui/lib/escher/geometry/types.h"
#include "src/ui/scenic/lib/sysmem/id.h"
namespace flatland {
// Typedef to a flatland type.
using Rectangle2D = escher::Rectangle2D;
// Used to reference a particular flatland image.
using GlobalImageId = uint64_t;
// Contains information regarding the constraints of a particular buffer collection. This
// should be used by the Flatland instance to check that images it wishes to create are
// valid. More information may be added to this struct over time.
struct BufferCollectionMetadata {
// The number of vmos available in the buffer collection.
uint32_t vmo_count;
// Various image constraint information, including max width/height and supported
// pixel formats. See |constraints.fidl| for more information.
fuchsia::sysmem::ImageFormatConstraints image_constraints;
};
// Struct representing the data needed to extract an image from a buffer collection.
// All pixel information is stored within the Vmo of the collection so this struct
// only needs information regarding which collection and which vmo to point to, and
// the overall size of the image. Only supports fuchsia::sysmem::PixelFormatType::BGRA32
// as the image format type.
struct ImageMetadata {
// The unique id of the buffer collection to refer to. This id should match an
// an ID generated by a call to |Renderer::RegisterBufferCollection| below.
sysmem_util::GlobalBufferCollectionId collection_id;
// The unique ID for this particular image.
GlobalImageId identifier;
// A single buffer collection may have several vmos. This tells the renderer
// which vmo in the collection specified by |collection_id| to use as the memory
// for this image. This value must be less than BufferCollectionMetadata::vmo_count.
uint32_t vmo_idx;
// The dimensions of the image in pixels.
uint32_t width, height;
bool operator==(const ImageMetadata& meta) const {
return collection_id == meta.collection_id && vmo_idx == meta.vmo_idx && width == meta.width &&
height == meta.height;
}
};
// This is the main renderer interface used by the Flatland System. Since Flatland is
// agnostic to the implementation of the renderer, it is declared here as a virtual
// interface, whose concrete implementation is to be injected into Flatland.
class Renderer {
public:
// This function registers a buffer collection with the renderer and is intended to be
// called by a Flatland instance on that instance's thread, not the render thread. It is
// thread safe, and so multiple Flatland instances can call it simultaneously. The
// buffer collection associated with an image must be registered with the renderer before
// that image can be used during rendering. Concrete implementations of this class may
// potentially set their own additional constraints on the buffer collection, including
// negotiating with the display controller.
//
// This function returns true upon a successful registration and false otherwise.
// Registration may fail if the passed in token is invalid or if it is a valid
// channel but not a valid buffer collection.
//
// It is the client's responsibility to provide a GlobalBufferCollectionID and to hold onto
// that ID to reference the buffer collection in subsequent calls. IDs must be positive,
// so an ID value of 0 will result in a failed registration.
//
// Passing in an ID that is already in use by another collection will also result in a return
// value of false. An ID can be reused if the buffer collection associated with the ID has
// been removed from the renderer via a call to |DeregisterBufferCollection|.
virtual bool RegisterTextureCollection(
sysmem_util::GlobalBufferCollectionId collection_id,
fuchsia::sysmem::Allocator_Sync* sysmem_allocator,
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token) = 0;
// This function operates exactly like the function |RegisterTextureCollection|, but is
// specifically for registering collections that contain render targets. In order for an image
// to be used as a render target in the Render() function below, the buffer collection it
// is associated with must have been registered with this function.
//
// This function is likewise threadsafe, although it is only meant to be called from the render
// loop, and not by any flatland instance directly.
virtual bool RegisterRenderTargetCollection(
sysmem_util::GlobalBufferCollectionId collection_id,
fuchsia::sysmem::Allocator_Sync* sysmem_allocator,
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token) = 0;
// Removes the buffer collection provided from the renderer. All images created using
// this buffer collection become invalid afterwards and no new images can be created using
// this collection id. Buffer collections can only be safely deregisted after all pending
// render work involving the collection has been completed. Deregistering before this point
// results in undefined behavior and may crash the process. To avoid this, it is possible
// to synchronize with rendering by passing a release fence in the form of a zx::event to
// Render() and waiting for it to signal before deregistering. See Render() for more details.
// This function is threadsafe.
//
// Once a buffer collection has been deregistered, the collection_id associated with it will
// be free to be reused again for a new collection.
virtual void DeregisterCollection(sysmem_util::GlobalBufferCollectionId collection_id) = 0;
// This function validates if the buffer collection referenced by |collection_id| is ready to
// be used in rendering operations and must be called before that buffer collection is used
// in |Render|. Specifically, this function checks to make sure that the buffer collection is
// fully allocated (which can only happen after all token holders have set constraints and the
// client has requested for sysmem to allocate the buffer collection via a call to
// WaitForBuffersAllocated() or an equivalent function).
//
// If the collection has not yet been fully allocated, or if the collection has not been
// registered with the renderer via a call to RegisterBufferCollection(), this function will
// return std::nullopt. If the collection has been registered and has been fully allocated, then
// this function will return a BufferCollectionMetadata struct containing information pertaining
// to the number of vmos as well as image constraints, such as maximum width/height (see
// BufferCollectionMetadata at the top of this file for more information).
//
// The BufferCollectionMetadata can then be used by the Flatland instance to verify images it
// wishes to create with this buffer collection. Images map N:1 with buffer collections, since a
// collection can consist of multiple VMOs, and each VMO in turn can back multiple images. The
// intended usage then is for the Flatland instance to store the BufferCollectionMetadata it
// receives and use it to compare against any incoming images. For example, if a buffer collection
// only has 5 VMOs and an image is referencing vmo index 6, then that would be an error.
//
// This function needs to be separate from RegisterBufferCollection() since it is too early to
// return a |BufferCollectionMetadata| struct at registration time., as the client may have not
// yet set their constraints, or duplicated their token. Combining this function with the above
// registration function would require us to block on registration, which could go on forever.
//
// Lastly, this function needs to communicate with sysmem and may take some time. However, it does
// not block indefinitely. Additionally, it only needs to be called once per buffer collection if
// the call was successful. It is up to the Flatland instance how to proceed in the event of
// failure. Calling this function multiple times until it returns true is allowed.
virtual std::optional<BufferCollectionMetadata> Validate(
sysmem_util::GlobalBufferCollectionId collection_id) = 0;
// This function is responsible for rendering a single batch of Flatland rectangles into a
// render target. This function is designed to be called on the render thread, not on any
// Flatland instance thread. The specific behavior may differ depending on the specific subclass
// implementation, which may also be a null renderer.
//
// This function assumes that clients have already validated their input data by comparing it
// against the BufferCollectionMetadata received from calling |Validate| above. This function
// will abort if invalid data has been passed in or if |Validate| has never been called.
//
// The size of the arrays |rectangles| and |images| must match or else this function will CHECK.
// Entries in each array with the same index will be used together in rendering.
//
// The vector of release fences will be signaled once rendering has completed. Clients can use
// these fences to coordinate with other work that needs to wait until rendering is completed
// to be executed.
virtual void Render(const ImageMetadata& render_target,
const std::vector<Rectangle2D>& rectangles,
const std::vector<ImageMetadata>& images,
const std::vector<zx::event>& release_fences = {}) = 0;
virtual ~Renderer() = default;
};
} // namespace flatland
#endif // SRC_UI_SCENIC_LIB_FLATLAND_RENDERER_RENDERER_H_