blob: dc2f7046e925b2d4185647e3cd84dc96b1c5415e [file]
// Copyright 2013 The Flutter 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 FLUTTER_IMPELLER_PLAYGROUND_PLAYGROUND_H_
#define FLUTTER_IMPELLER_PLAYGROUND_PLAYGROUND_H_
#include <chrono>
#include <memory>
#include "flutter/fml/status.h"
#include "flutter/fml/time/time_delta.h"
#include "impeller/core/host_buffer.h"
#include "impeller/core/runtime_types.h"
#include "impeller/core/texture.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/geometry/point.h"
#include "impeller/playground/image/compressed_image.h"
#include "impeller/playground/image/decompressed_image.h"
#include "impeller/playground/switches.h"
#include "impeller/renderer/render_target.h"
namespace impeller {
class PlaygroundImpl;
enum class PlaygroundBackend {
kMetal,
kMetalSDF,
kOpenGLES,
kOpenGLESSDF,
kVulkan,
};
std::string PlaygroundBackendToString(PlaygroundBackend backend);
class Playground {
public:
using SinglePassCallback = std::function<bool(RenderPass& pass)>;
explicit Playground(PlaygroundBackend backend,
const PlaygroundSwitches& switches);
virtual ~Playground();
static bool ShouldOpenNewPlaygrounds();
bool IsPlaygroundEnabled() const;
Point GetCursorPosition() const;
ISize GetWindowSize() const;
IRect GetWindowBounds() const;
Point GetContentScale() const;
/// @brief Get the amount of time elapsed from the start of the playground's
/// execution.
Scalar GetSecondsElapsed() const;
std::shared_ptr<Context> GetContext() const;
std::shared_ptr<Context> MakeContext() const;
ContentContext& GetContentContext() const;
std::shared_ptr<TypographerContext> GetTypographerContext() const;
using RenderCallback = std::function<bool(RenderTarget& render_target)>;
bool OpenPlaygroundHere(const RenderCallback& render_callback);
bool OpenPlaygroundHere(SinglePassCallback pass_callback);
static std::shared_ptr<CompressedImage> LoadFixtureImageCompressed(
std::shared_ptr<fml::Mapping> mapping);
static std::optional<DecompressedImage> DecodeImageRGBA(
const std::shared_ptr<CompressedImage>& compressed);
static std::shared_ptr<Texture> CreateTextureForMapping(
const std::shared_ptr<Context>& context,
std::shared_ptr<fml::Mapping> mapping,
bool enable_mipmapping = false);
std::shared_ptr<Texture> CreateTextureForFixture(
const char* fixture_name,
bool enable_mipmapping = false) const;
std::shared_ptr<Texture> CreateTextureCubeForFixture(
std::array<const char*, 6> fixture_names) const;
static bool SupportsBackend(PlaygroundBackend backend);
virtual std::unique_ptr<fml::Mapping> OpenAssetAsMapping(
std::string asset_name) const = 0;
virtual std::string GetWindowTitle() const = 0;
[[nodiscard]] fml::Status SetCapabilities(
const std::shared_ptr<Capabilities>& capabilities);
/// Returns true if `OpenPlaygroundHere` will actually render anything.
bool WillRenderSomething() const;
using GLProcAddressResolver = std::function<void*(const char* proc_name)>;
GLProcAddressResolver CreateGLProcAddressResolver() const;
using VKProcAddressResolver =
std::function<void*(void* instance, const char* proc_name)>;
VKProcAddressResolver CreateVKProcAddressResolver() const;
/// @brief Mark the GPU as unavilable.
///
/// Only supported on the Metal backend.
void SetGPUDisabled(bool disabled) const;
RuntimeStageBackend GetRuntimeStageBackend() const;
protected:
// This method could override testing::Test::TearDown() directly, but
// since we don't inherit from that Test class the override would not
// be recognized. Instead we make this method available to subclasses
// that do inherit from testing::Test so that they can redirect to
// it during test teardown.
void TearDownContextData();
virtual bool ShouldKeepRendering() const;
/// @brief Make sure that when the context is later created that it
/// will not be shared with any other playgrounds.
///
/// Must be called before any other method except for the Ensure family
/// of methods.
virtual void EnsureContextIsUnique();
/// @brief Returns true if the platform can support wide gamuts.
bool PlatformSupportsWideGamutTests() const;
/// @brief Make sure that when the context is later created that it
/// will support wide gamuts if the platform supports it.
/// Returns whether the platform supports wide gamut.
///
/// Must be called before any other method except for the Ensure family
/// of methods.
///
/// Callers should abort (such as via GTEST_SKIP) if the method returns
/// false if their behavior depends on the wide gamut support.
///
/// @see PlatformSupportsWideGamut()
[[nodiscard]] virtual bool EnsureContextSupportsWideGamut();
/// @brief Make sure that when the context is later created that it
/// will support the experimental AA lines flag.
///
/// Must be called before any other method except for the Ensure family
/// of methods.
virtual void EnsureContextSupportsAntialiasLines();
/// @brief Return an unmodifiable reference to the current switches.
/// The switches might change at the start of a test as it
/// has a brief opportunity to call any of the Ensure* methods
/// that define the environment it expects, but should be
/// stable by the time any subsequent methods that might perform
/// work are called.
const PlaygroundSwitches& GetSwitches() const { return switches_; }
void SetTypographerContext(
std::shared_ptr<TypographerContext> typographer_context);
void SetWindowSize(ISize size);
private:
const PlaygroundBackend backend_;
PlaygroundSwitches switches_;
fml::TimeDelta start_time_;
// The following state variables are created lazily because not every
// playground instance uses them. Most, if not all, do use the |impl_|
// and |context_| implicitly, especially when running with the playground
// window enabled, but the content and typographer contexts are only used
// by a small portion of the unit tests.
//
// Since they are created lazily upon first reference, they are triggered
// by const getter methods and so need to be mutable for the first call
// when they get initialized.
mutable std::unique_ptr<PlaygroundImpl> impl_;
mutable std::shared_ptr<Context> context_;
mutable std::unique_ptr<ContentContext> content_context_;
mutable std::shared_ptr<TypographerContext> typographer_context_;
Point cursor_position_;
ISize window_size_ = ISize{1024, 768};
std::shared_ptr<HostBuffer> host_buffer_;
std::unique_ptr<PlaygroundImpl>& GetImpl() const;
void SetupContext() const;
void SetupWindow();
void SetCursorPosition(Point pos);
Playground(const Playground&) = delete;
Playground& operator=(const Playground&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_PLAYGROUND_PLAYGROUND_H_