| // 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 "src/ui/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 |