blob: 461bd75b49c71919db5baccaadb6646684ddb029 [file] [log] [blame]
// 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.
#include "flutter/skwasm/render_context.h"
#include "flutter/impeller/display_list/dl_dispatcher.h"
#include "flutter/impeller/entity/gles3/entity_shaders_gles.h"
#include "flutter/impeller/renderer/backend/gles/context_gles.h"
#include "flutter/impeller/renderer/backend/gles/surface_gles.h"
#include "flutter/impeller/typographer/backends/skia/text_frame_skia.h"
#include "flutter/impeller/typographer/backends/skia/typographer_context_skia.h"
#include "flutter/skwasm/export.h"
SKWASM_EXPORT bool skwasm_isWimp() {
return true;
}
namespace {
std::vector<std::shared_ptr<fml::Mapping>>
ShaderLibraryMappingsForApplication() {
return {
std::make_shared<fml::NonOwnedMapping>(
impeller_entity_shaders_gles3_data,
impeller_entity_shaders_gles3_length),
};
}
class ReactorWorker : public impeller::ReactorGLES::Worker {
public:
ReactorWorker() = default;
ReactorWorker(const ReactorWorker&) = delete;
ReactorWorker& operator=(const ReactorWorker&) = delete;
virtual bool CanReactorReactOnCurrentThreadNow(
const impeller::ReactorGLES& reactor) const override {
return true;
}
};
class ImpellerRenderContext : public Skwasm::RenderContext {
public:
ImpellerRenderContext(std::shared_ptr<impeller::ContextGLES> context,
std::shared_ptr<ReactorWorker> worker)
: context_(std::move(context)),
worker_(std::move(worker)),
typographer_context_(impeller::TypographerContextSkia::Make()),
content_context_(
std::make_unique<impeller::ContentContext>(context_,
typographer_context_,
nullptr)) {}
virtual void RenderPicture(
const sk_sp<flutter::DisplayList> display_list) override {
impeller::RenderToTarget(
*content_context_, surface_->GetRenderTarget(), display_list,
impeller::Rect::MakeLTRB(0, 0, width_, height_), true);
}
virtual void RenderImage(flutter::DlImage* image,
Skwasm::ImageByteFormat format) override {}
virtual void Resize(int width, int height) override {
if (width_ != width || height_ != height) {
width_ = width;
height_ = height;
RecreateSurface();
}
}
virtual void SetResourceCacheLimit(int bytes) override {
// No-op
}
private:
void RecreateSurface() {
surface_ = impeller::SurfaceGLES::WrapFBO(
/*context=*/context_,
/*swap_callback=*/[]() { return true; },
/*fbo=*/0u,
/*color_format=*/impeller::PixelFormat::kR8G8B8A8UNormInt,
/*fbo_size=*/{width_, height_});
}
std::shared_ptr<impeller::ContextGLES> context_;
std::shared_ptr<ReactorWorker> worker_;
std::shared_ptr<impeller::TypographerContext> typographer_context_;
std::unique_ptr<impeller::ContentContext> content_context_;
std::unique_ptr<impeller::Surface> surface_;
int width_ = 0;
int height_ = 0;
};
} // namespace
std::unique_ptr<Skwasm::RenderContext> Skwasm::RenderContext::Make(
int sample_count,
int stencil) {
auto clear_depth_emulated = [](float depth) {};
auto depth_range_emulated = [](float near_val, float far_val) {};
std::map<std::string, void*> gl_procs;
gl_procs["glGetError"] = (void*)&glGetError;
gl_procs["glClearDepthf"] = (void*)&clear_depth_emulated;
gl_procs["glDepthRangef"] = (void*)&depth_range_emulated;
#define IMPELLER_PROC(name) gl_procs["gl" #name] = (void*)&gl##name;
FOR_EACH_IMPELLER_PROC(IMPELLER_PROC);
FOR_EACH_IMPELLER_ES_ONLY_PROC(IMPELLER_PROC);
FOR_EACH_IMPELLER_GLES3_PROC(IMPELLER_PROC);
IMPELLER_PROC(GenQueriesEXT);
IMPELLER_PROC(DeleteQueriesEXT);
IMPELLER_PROC(GetQueryObjectui64vEXT);
IMPELLER_PROC(BeginQueryEXT);
IMPELLER_PROC(EndQueryEXT);
IMPELLER_PROC(GetQueryObjectuivEXT);
#undef IMPELLER_PROC
auto gl = std::make_unique<impeller::ProcTableGLES>(
[gl_procs = std::move(gl_procs)](const char* function_name) -> void* {
auto found = gl_procs.find(function_name);
if (found == gl_procs.end()) {
return nullptr;
}
return found->second;
});
auto context = impeller::ContextGLES::Create(
impeller::Flags{}, std::move(gl), ShaderLibraryMappingsForApplication(),
false);
auto worker = std::make_shared<ReactorWorker>();
context->AddReactorWorker(worker);
return std::make_unique<ImpellerRenderContext>(std::move(context),
std::move(worker));
}