blob: 72938134c42a99203d8f8c3a0f14240d907ffbad [file] [log] [blame]
// Copyright 2017 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.
#include "garnet/examples/ui/shadertoy/service/shadertoy_state.h"
#include "garnet/examples/ui/shadertoy/service/app.h"
#include "garnet/examples/ui/shadertoy/service/imagepipe_shadertoy.h"
#include "garnet/examples/ui/shadertoy/service/pipeline.h"
#include "garnet/examples/ui/shadertoy/service/renderer.h"
#include "garnet/examples/ui/shadertoy/service/view_shadertoy.h"
#include "lib/escher/resources/resource_recycler.h"
namespace shadertoy {
fxl::RefPtr<ShadertoyState> ShadertoyState::NewForImagePipe(
App* app, fidl::InterfaceHandle<fuchsia::images::ImagePipe> image_pipe) {
return fxl::AdoptRef(
new ShadertoyStateForImagePipe(app, std::move(image_pipe)));
}
fxl::RefPtr<ShadertoyState> ShadertoyState::NewForView(
App* app, zx::eventpair view_token, bool handle_input_events) {
FXL_CHECK(false) << "unimplemented.";
return fxl::RefPtr<ShadertoyState>();
#if 0
return fxl::AdoptRef(new ShadertoyStateForView(
app, std::move(view_token), handle_input_events));
#endif
}
ShadertoyState::ShadertoyState(App* app)
: escher::Resource(app->escher()->resource_recycler()),
app_(app),
escher_(app_->escher()->GetWeakPtr()),
compiler_(app_->compiler()),
renderer_(app_->renderer()),
weak_ptr_factory_(this),
stopwatch_(false) {}
ShadertoyState::~ShadertoyState() = default;
void ShadertoyState::SetPaused(bool paused) {
is_paused_ = paused;
if (is_paused_) {
stopwatch_.Stop();
} else {
stopwatch_.Start();
}
RequestFrame(0);
}
void ShadertoyState::SetShaderCode(
fidl::StringPtr glsl,
fuchsia::examples::shadertoy::Shadertoy::SetShaderCodeCallback callback) {
compiler_->Compile(std::string(glsl),
[weak = weak_ptr_factory_.GetWeakPtr(),
callback = std::move(callback)](Compiler::Result result) {
if (weak) {
if (result.pipeline) {
// Notify client that the code was successfully
// compiled.
callback(true);
// Start rendering with the new pipeline.
weak->pipeline_ = std::move(result.pipeline);
weak->RequestFrame(0);
} else {
// Notify client that the code could not be
// successfully compiled.
callback(false);
}
}
});
}
void ShadertoyState::SetResolution(uint32_t width, uint32_t height) {
if (width == width_ && height == height_) {
return;
}
if (width > kMaxWidth) {
FXL_LOG(ERROR) << "Resolution max width exceeded, " << width << " > "
<< kMaxWidth;
return;
}
if (height > kMaxHeight) {
FXL_LOG(ERROR) << "Resolution max height exceeded, " << height << " > "
<< kMaxHeight;
return;
}
width_ = width;
height_ = height;
OnSetResolution();
RequestFrame(0);
}
void ShadertoyState::SetMouse(glm::vec4 i_mouse) {
if (i_mouse != i_mouse_) {
i_mouse_ = i_mouse;
RequestFrame(0);
}
}
void ShadertoyState::SetImage(
uint32_t channel,
fidl::InterfaceRequest<fuchsia::images::ImagePipe> request) {
FXL_CHECK(false) << "unimplemented";
}
void ShadertoyState::RequestFrame(uint64_t presentation_time) {
if (is_drawing_ || is_paused_ || is_closed_ || !pipeline_ ||
(width_ * height_ == 0)) {
return;
}
is_drawing_ = true;
// The stars have aligned; draw a frame.
DrawFrame(presentation_time, stopwatch_.GetElapsedSeconds());
// Ensure that all frames are finished before this object is destroyed.
KeepAlive(escher()->command_buffer_sequencer()->latest_sequence_number());
}
void ShadertoyState::OnFramePresented(fuchsia::images::PresentationInfo info) {
FXL_DCHECK(is_drawing_);
is_drawing_ = false;
RequestFrame(info.presentation_time + info.presentation_interval);
}
void ShadertoyState::Close() {
if (!is_closed_) {
is_closed_ = true;
KeepAlive(escher()->command_buffer_sequencer()->latest_sequence_number());
app_->CloseShadertoy(this);
}
}
} // namespace shadertoy