15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <queue> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/atomic_ref_count.h" 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/atomicops.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/linked_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/memory/shared_memory.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/cmd_buffer_engine.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/cmd_parser.h" 20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "gpu/command_buffer/service/command_buffer_service.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/gles2_cmd_decoder.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/gpu_export.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GLFence; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PreemptionFlag 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : public base::RefCountedThreadSafe<PreemptionFlag> { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PreemptionFlag() : flag_(0) {} 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool IsSet() { return !base::AtomicRefCountIsZero(&flag_); } 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Set() { base::AtomicRefCountInc(&flag_); } 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Reset() { base::subtle::NoBarrier_Store(&flag_, 0); } 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AtomicRefCount flag_; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~PreemptionFlag() {} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) friend class base::RefCountedThreadSafe<PreemptionFlag>; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class schedules commands that have been flushed. They are received via 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a command buffer and forwarded to a command parser. TODO(apatrick): This 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// class should not know about the decoder. Do not add additional dependencies 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on it. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GPU_EXPORT GpuScheduler 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : NON_EXPORTED_BASE(public CommandBufferEngine), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::SupportsWeakPtr<GpuScheduler> { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch GpuScheduler(CommandBufferServiceBase* command_buffer, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsyncAPIInterface* handler, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gles2::GLES2Decoder* decoder); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GpuScheduler(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PutChanged(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetPreemptByFlag(scoped_refptr<PreemptionFlag> flag) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) preemption_flag_ = flag; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets whether commands should be processed by this scheduler. Setting to 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // false unschedules. Setting to true reschedules. Whether or not the 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scheduler is currently scheduled is "reference counted". Every call with 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // false must eventually be paired by a call with true. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetScheduled(bool is_scheduled); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns whether the scheduler is currently able to process more commands. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsScheduled(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns whether the scheduler needs to be polled again in the future. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool HasMoreWork(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef base::Callback<void(bool /* scheduled */)> SchedulingChangedCallback; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Sets a callback that is invoked just before scheduler is rescheduled 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // or descheduled. Takes ownership of callback object. 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetSchedulingChangedCallback(const SchedulingChangedCallback& callback); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Implementation of CommandBufferEngine. 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch virtual scoped_refptr<Buffer> GetSharedMemoryBuffer(int32 shm_id) OVERRIDE; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void set_token(int32 token) OVERRIDE; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool SetGetBuffer(int32 transfer_buffer_id) OVERRIDE; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool SetGetOffset(int32 offset) OVERRIDE; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int32 GetGetOffset() OVERRIDE; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetCommandProcessedCallback(const base::Closure& callback); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeferToFence(base::Closure task); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Polls the fences, invoking callbacks that were waiting to be triggered 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by them and returns whether all fences were complete. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool PollUnscheduleFences(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool HasMoreIdleWork(); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PerformIdleWork(); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandParser* parser() const { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return parser_.get(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool IsPreempted(); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Artificially reschedule if the scheduler is still unscheduled after a 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // timeout. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RescheduleTimeOut(); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The GpuScheduler holds a weak reference to the CommandBuffer. The 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CommandBuffer owns the GpuScheduler and holds a strong reference to it 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // through the ProcessCommands callback. 117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch CommandBufferServiceBase* command_buffer_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The parser uses this to execute commands. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsyncAPIInterface* handler_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Does not own decoder. TODO(apatrick): The GpuScheduler shouldn't need a 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointer to the decoder, it is only used to initialize the CommandParser, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which could be an argument to the constructor, and to determine the 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reason for context lost. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gles2::GLES2Decoder* decoder_; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(apatrick): The GpuScheduler currently creates and owns the parser. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should be an argument to the constructor. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<CommandParser> parser_; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Greater than zero if this is waiting to be rescheduled before continuing. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unscheduled_count_; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The number of times this scheduler has been artificially rescheduled on 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // account of a timeout. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rescheduled_count_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The GpuScheduler will unschedule itself in the event that further GL calls 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are issued to it before all these fences have been crossed by the GPU. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct UnscheduleFence { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnscheduleFence(gfx::GLFence* fence, base::Closure task); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~UnscheduleFence(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<gfx::GLFence> fence; 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Time issue_time; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure task; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<linked_ptr<UnscheduleFence> > unschedule_fences_; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulingChangedCallback scheduling_changed_callback_; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Closure descheduled_callback_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure command_processed_callback_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If non-NULL and |preemption_flag_->IsSet()|, exit PutChanged early. 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<PreemptionFlag> preemption_flag_; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_preempted_; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // A factory for outstanding rescheduling tasks that is invalidated whenever 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the scheduler is rescheduled. 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtrFactory<GpuScheduler> reschedule_task_factory_; 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(GpuScheduler); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gpu 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_ 169