| // 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. Whether or not the |
| // scheduler is currently scheduled is "reference counted". Every call with |
| // false must eventually be paired by a call with true. |
| void SetScheduled(bool is_scheduled); |
| |
| // Returns whether the scheduler is currently able to process more commands. |
| bool IsScheduled(); |
| |
| // Returns whether the scheduler needs to be polled again in the future. |
| bool HasMoreWork(); |
| |
| 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); |
| |
| bool HasMoreIdleWork(); |
| void PerformIdleWork(); |
| |
| CommandParser* parser() const { |
| return parser_.get(); |
| } |
| |
| bool IsPreempted(); |
| |
| private: |
| // Artificially reschedule if the scheduler is still unscheduled after a |
| // timeout. |
| void RescheduleTimeOut(); |
| |
| // 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_; |
| |
| // Greater than zero if this is waiting to be rescheduled before continuing. |
| int unscheduled_count_; |
| |
| // The number of times this scheduler has been artificially rescheduled on |
| // account of a timeout. |
| int rescheduled_count_; |
| |
| 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_; |
| |
| // A factory for outstanding rescheduling tasks that is invalidated whenever |
| // the scheduler is rescheduled. |
| base::WeakPtrFactory<GpuScheduler> reschedule_task_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(GpuScheduler); |
| }; |
| |
| } // namespace gpu |
| |
| #endif // GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_ |