| // Copyright (c) 2012 The Chromium 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 GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_ |
| #define GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_ |
| |
| #include <queue> |
| |
| #include "base/atomic_ref_count.h" |
| #include "base/atomicops.h" |
| #include "base/callback.h" |
| #include "base/memory/linked_ptr.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/shared_memory.h" |
| #include "base/memory/weak_ptr.h" |
| #include "gpu/command_buffer/service/cmd_buffer_engine.h" |
| #include "gpu/command_buffer/service/cmd_parser.h" |
| #include "gpu/command_buffer/service/command_buffer_service.h" |
| #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| #include "gpu/gpu_export.h" |
| |
| namespace gfx { |
| class GLFence; |
| } |
| |
| namespace gpu { |
| |
| class PreemptionFlag |
| : public base::RefCountedThreadSafe<PreemptionFlag> { |
| public: |
| PreemptionFlag() : flag_(0) {} |
| |
| bool IsSet() { return !base::AtomicRefCountIsZero(&flag_); } |
| void Set() { base::AtomicRefCountInc(&flag_); } |
| void Reset() { base::subtle::NoBarrier_Store(&flag_, 0); } |
| |
| private: |
| base::AtomicRefCount flag_; |
| |
| ~PreemptionFlag() {} |
| |
| friend class base::RefCountedThreadSafe<PreemptionFlag>; |
| }; |
| |
| // This class schedules commands that have been flushed. They are received via |
| // a command buffer and forwarded to a command parser. TODO(apatrick): This |
| // class should not know about the decoder. Do not add additional dependencies |
| // on it. |
| class GPU_EXPORT GpuScheduler |
| : NON_EXPORTED_BASE(public CommandBufferEngine), |
| public base::SupportsWeakPtr<GpuScheduler> { |
| public: |
| GpuScheduler(CommandBufferServiceBase* command_buffer, |
| AsyncAPIInterface* handler, |
| gles2::GLES2Decoder* decoder); |
| |
| ~GpuScheduler() override; |
| |
| void PutChanged(); |
| |
| void SetPreemptByFlag(scoped_refptr<PreemptionFlag> flag) { |
| preemption_flag_ = flag; |
| } |
| |
| // Sets whether commands should be processed by this scheduler. Setting to |
| // false unschedules. Setting to true reschedules. |
| void SetScheduled(bool scheduled); |
| |
| bool scheduled() const { return scheduled_; } |
| |
| // Returns whether the scheduler needs to be polled again in the future to |
| // process pending queries. |
| bool HasPendingQueries() const; |
| |
| // Process pending queries and return. HasPendingQueries() can be used to |
| // determine if there's more pending queries after this has been called. |
| void ProcessPendingQueries(); |
| |
| typedef base::Callback<void(bool /* scheduled */)> SchedulingChangedCallback; |
| |
| // Sets a callback that is invoked just before scheduler is rescheduled |
| // or descheduled. Takes ownership of callback object. |
| void SetSchedulingChangedCallback(const SchedulingChangedCallback& callback); |
| |
| // Implementation of CommandBufferEngine. |
| scoped_refptr<Buffer> GetSharedMemoryBuffer(int32 shm_id) override; |
| void set_token(int32 token) override; |
| bool SetGetBuffer(int32 transfer_buffer_id) override; |
| bool SetGetOffset(int32 offset) override; |
| int32 GetGetOffset() override; |
| |
| void SetCommandProcessedCallback(const base::Closure& callback); |
| |
| // Returns whether the scheduler needs to be polled again in the future to |
| // process idle work. |
| bool HasMoreIdleWork() const; |
| |
| // Perform some idle work and return. HasMoreIdleWork() can be used to |
| // determine if there's more idle work do be done after this has been called. |
| void PerformIdleWork(); |
| |
| CommandParser* parser() const { |
| return parser_.get(); |
| } |
| |
| private: |
| bool IsPreempted(); |
| |
| // The GpuScheduler holds a weak reference to the CommandBuffer. The |
| // CommandBuffer owns the GpuScheduler and holds a strong reference to it |
| // through the ProcessCommands callback. |
| CommandBufferServiceBase* command_buffer_; |
| |
| // The parser uses this to execute commands. |
| AsyncAPIInterface* handler_; |
| |
| // Does not own decoder. TODO(apatrick): The GpuScheduler shouldn't need a |
| // pointer to the decoder, it is only used to initialize the CommandParser, |
| // which could be an argument to the constructor, and to determine the |
| // reason for context lost. |
| gles2::GLES2Decoder* decoder_; |
| |
| // TODO(apatrick): The GpuScheduler currently creates and owns the parser. |
| // This should be an argument to the constructor. |
| scoped_ptr<CommandParser> parser_; |
| |
| // Whether the scheduler is currently able to process more commands. |
| bool scheduled_; |
| |
| SchedulingChangedCallback scheduling_changed_callback_; |
| base::Closure descheduled_callback_; |
| base::Closure command_processed_callback_; |
| |
| // If non-NULL and |preemption_flag_->IsSet()|, exit PutChanged early. |
| scoped_refptr<PreemptionFlag> preemption_flag_; |
| bool was_preempted_; |
| |
| DISALLOW_COPY_AND_ASSIGN(GpuScheduler); |
| }; |
| |
| } // namespace gpu |
| |
| #endif // GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_ |