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)#include "base/bind.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/hash.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/json/json_writer.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/shared_memory.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/common/gpu/devtools_gpu_instrumentation.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_channel.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_channel_manager.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_command_buffer_stub.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/gpu/gpu_memory_buffer_factory.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_memory_manager.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_memory_tracking.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_watchdog.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/image_transport_surface.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/sync_point_manager.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_client.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/constants.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/gles2_cmd_utils.h"
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "gpu/command_buffer/common/mailbox.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/service/gl_context_virtual.h"
32a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "gpu/command_buffer/service/gl_state_restorer_impl.h"
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "gpu/command_buffer/service/image_manager.h"
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "gpu/command_buffer/service/logger.h"
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gpu/command_buffer/service/mailbox_manager.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/memory_tracking.h"
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "gpu/command_buffer/service/query_manager.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_switches.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/sandbox_init.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/gpu/stream_texture_android.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstruct WaitForCommandState {
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  WaitForCommandState(int32 start, int32 end, IPC::Message* reply)
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      : start(start), end(end), reply(reply) {}
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int32 start;
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int32 end;
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<IPC::Message> reply;
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The GpuCommandBufferMemoryTracker class provides a bridge between the
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ContextGroup's memory type managers and the GpuMemoryManager class.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GpuCommandBufferMemoryTracker : public gpu::gles2::MemoryTracker {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit GpuCommandBufferMemoryTracker(GpuChannel* channel) :
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tracking_group_(channel->gpu_channel_manager()->gpu_memory_manager()->
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          CreateTrackingGroup(channel->renderer_pid(), this)) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TrackMemoryAllocatedChange(
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_t old_size,
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_t new_size,
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gpu::gles2::MemoryTracker::Pool pool) OVERRIDE {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tracking_group_->TrackMemoryAllocatedChange(
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        old_size, new_size, pool);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool EnsureGPUMemoryAvailable(size_t size_needed) OVERRIDE {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return tracking_group_->EnsureGPUMemoryAvailable(size_needed);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~GpuCommandBufferMemoryTracker() {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<GpuMemoryTrackingGroup> tracking_group_;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferMemoryTracker);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastSetActiveURL will shortcut the expensive call to SetActiveURL when the
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// url_hash matches.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FastSetActiveURL(const GURL& url, size_t url_hash) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Leave the previously set URL in the empty case -- empty URLs are given by
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebKitPlatformSupportImpl::createOffscreenGraphicsContext3D. Hopefully the
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // onscreen context URL was set previously and will show up even when a crash
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // occurs during offscreen command processing.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.is_empty())
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static size_t g_last_url_hash = 0;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url_hash != g_last_url_hash) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_last_url_hash = url_hash;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetContentClient()->SetActiveURL(url);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The first time polling a fence, delay some extra time to allow other
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stubs to process some work, or else the timing of the fences could
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allow a pattern of alternating fast and slow frames to occur.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 kHandleMoreWorkPeriodMs = 2;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 kHandleMoreWorkPeriodBusyMs = 1;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Prevents idle work from being starved.
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kMaxTimeSinceIdleMs = 10;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DevToolsChannelData : public base::debug::ConvertableToTraceFormat {
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  static scoped_refptr<base::debug::ConvertableToTraceFormat> CreateForChannel(
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GpuChannel* channel);
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::string tmp;
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::JSONWriter::Write(value_.get(), &tmp);
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *out += tmp;
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  explicit DevToolsChannelData(base::Value* value) : value_(value) {}
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~DevToolsChannelData() {}
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<base::Value> value_;
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DevToolsChannelData);
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_refptr<base::debug::ConvertableToTraceFormat>
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DevToolsChannelData::CreateForChannel(GpuChannel* channel) {
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue);
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  res->SetInteger("renderer_pid", channel->renderer_pid());
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  res->SetDouble("used_bytes", channel->GetMemoryUsage());
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  res->SetDouble("limit_bytes",
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 channel->gpu_channel_manager()
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     ->gpu_memory_manager()
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     ->GetMaximumClientAllocation());
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return new DevToolsChannelData(res.release());
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuCommandBufferStub::GpuCommandBufferStub(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuChannel* channel,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuCommandBufferStub* share_group,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::GLSurfaceHandle& handle,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu::gles2::MailboxManager* mailbox_manager,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gpu::gles2::DisallowedFeatures& disallowed_features,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<int32>& attribs,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::GpuPreference gpu_preference,
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool use_virtualized_gl_context,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 route_id,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 surface_id,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuWatchdog* watchdog,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool software,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& active_url)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : channel_(channel),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handle_(handle),
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_size_(size),
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disallowed_features_(disallowed_features),
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requested_attribs_(attribs),
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gpu_preference_(gpu_preference),
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      use_virtualized_gl_context_(use_virtualized_gl_context),
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      route_id_(route_id),
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      surface_id_(surface_id),
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      software_(software),
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_flush_count_(0),
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_memory_allocation_valid_(false),
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      watchdog_(watchdog),
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_point_wait_count_(0),
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delayed_work_scheduled_(false),
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      previous_messages_processed_(0),
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      active_url_(active_url),
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_gpu_memory_(0) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_url_hash_ = base::Hash(active_url.possibly_invalid_spec());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FastSetActiveURL(active_url_, active_url_hash_);
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gpu::gles2::ContextCreationAttribHelper attrib_parser;
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  attrib_parser.Parse(requested_attribs_);
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (share_group) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_group_ = share_group->context_group_;
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DCHECK(context_group_->bind_generates_resource() ==
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)           attrib_parser.bind_generates_resource);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_group_ = new gpu::gles2::ContextGroup(
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mailbox_manager,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new GpuCommandBufferMemoryTracker(channel),
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        channel_->gpu_channel_manager()->shader_translator_cache(),
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        NULL,
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        attrib_parser.bind_generates_resource);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  use_virtualized_gl_context_ |=
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      context_group_->feature_info()->workarounds().use_virtualized_gl_contexts;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuCommandBufferStub::~GpuCommandBufferStub() {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu_channel_manager->Send(new GpuHostMsg_DestroyCommandBuffer(surface_id()));
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)GpuMemoryManager* GpuCommandBufferStub::GetMemoryManager() const {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return channel()->gpu_channel_manager()->gpu_memory_manager();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               "GPUTask",
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               "data",
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               DevToolsChannelData::CreateForChannel(channel()));
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // TODO(yurys): remove devtools_gpu_instrumentation call once DevTools
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Timeline migrates to tracing crbug.com/361045.
221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  devtools_gpu_instrumentation::ScopedGpuTask task(channel());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FastSetActiveURL(active_url_, active_url_hash_);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool have_context = false;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure the appropriate GL context is current before handling any IPC
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // messages directed at the command buffer. This ensures that the message
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handler can assume that the context is current (not necessary for
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Echo, RetireSyncPoint, or WaitSyncPoint).
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (decoder_.get() && message.type() != GpuCommandBufferMsg_Echo::ID &&
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      message.type() != GpuCommandBufferMsg_WaitForTokenInRange::ID &&
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      message.type() != GpuCommandBufferMsg_WaitForGetOffsetInRange::ID &&
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      message.type() != GpuCommandBufferMsg_RetireSyncPoint::ID) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!MakeCurrent())
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    have_context = true;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here. This is so the reply can be delayed if the scheduler is unscheduled.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_Initialize,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    OnInitialize);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetGetBuffer,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    OnSetGetBuffer);
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ProduceFrontBuffer,
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        OnProduceFrontBuffer);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Echo, OnEcho);
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_WaitForTokenInRange,
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                    OnWaitForTokenInRange);
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_WaitForGetOffsetInRange,
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                    OnWaitForGetOffsetInRange);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Rescheduled, OnRescheduled);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterTransferBuffer,
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnRegisterTransferBuffer);
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyTransferBuffer,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        OnDestroyTransferBuffer);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateVideoDecoder,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    OnCreateVideoDecoder)
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateVideoEncoder,
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                    OnCreateVideoEncoder)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetSurfaceVisible,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnSetSurfaceVisible)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RetireSyncPoint,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnRetireSyncPoint)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalSyncPoint,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnSignalSyncPoint)
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalQuery,
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        OnSignalQuery)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GpuCommandBufferMsg_SetClientHasMemoryAllocationChangedCallback,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OnSetClientHasMemoryAllocationChangedCallback)
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterGpuMemoryBuffer,
2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                        OnRegisterGpuMemoryBuffer);
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_UnregisterGpuMemoryBuffer,
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        OnUnregisterGpuMemoryBuffer);
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateStreamTexture,
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        OnCreateStreamTexture)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CheckCompleteWaits();
284c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (have_context) {
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Ensure that any delayed work that was created will be handled.
287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ScheduleDelayedWork(kHandleMoreWorkPeriodMs);
288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(handled);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuCommandBufferStub::Send(IPC::Message* message) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel_->Send(message);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuCommandBufferStub::IsScheduled() {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (!scheduler_.get() || scheduler_->IsScheduled());
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuCommandBufferStub::HasMoreWork() {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scheduler_.get() && scheduler_->HasMoreWork();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::PollWork() {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::PollWork");
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delayed_work_scheduled_ = false;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FastSetActiveURL(active_url_, active_url_hash_);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (decoder_.get() && !MakeCurrent())
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (scheduler_) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool fences_complete = scheduler_->PollUnscheduleFences();
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Perform idle work if all fences are complete.
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fences_complete) {
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uint64 current_messages_processed =
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          channel()->gpu_channel_manager()->MessagesProcessed();
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // We're idle when no messages were processed or scheduled.
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool is_idle =
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          (previous_messages_processed_ == current_messages_processed) &&
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          !channel()->gpu_channel_manager()->HandleMessagesScheduled();
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!is_idle && !last_idle_time_.is_null()) {
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta time_since_idle = base::TimeTicks::Now() -
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            last_idle_time_;
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta max_time_since_idle =
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::TimeDelta::FromMilliseconds(kMaxTimeSinceIdleMs);
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Force idle when it's been too long since last time we were idle.
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (time_since_idle > max_time_since_idle)
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          is_idle = true;
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (is_idle) {
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        last_idle_time_ = base::TimeTicks::Now();
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scheduler_->PerformIdleWork();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleDelayedWork(kHandleMoreWorkPeriodBusyMs);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuCommandBufferStub::HasUnprocessedCommands() {
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (command_buffer_) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu::CommandBuffer::State state = command_buffer_->GetLastState();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return state.put_offset != state.get_offset &&
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !gpu::error::IsError(state.error);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::ScheduleDelayedWork(int64 delay) {
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!HasMoreWork()) {
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_idle_time_ = base::TimeTicks();
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delayed_work_scheduled_)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delayed_work_scheduled_ = true;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Idle when no messages are processed between now and when
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // PollWork is called.
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  previous_messages_processed_ =
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      channel()->gpu_channel_manager()->MessagesProcessed();
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (last_idle_time_.is_null())
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_idle_time_ = base::TimeTicks::Now();
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // IsScheduled() returns true after passing all unschedule fences
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and this is when we can start performing idle work. Idle work
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is done synchronously so we can set delay to 0 and instead poll
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for more work at the rate idle work is performed. This also ensures
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // that idle work is done as efficiently as possible without any
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // unnecessary delays.
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (scheduler_.get() &&
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scheduler_->IsScheduled() &&
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scheduler_->HasMoreIdleWork()) {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delay = 0;
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()),
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(delay));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnEcho(const IPC::Message& message) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnEcho");
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new IPC::Message(message));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GpuCommandBufferStub::MakeCurrent() {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (decoder_->MakeCurrent())
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG(ERROR) << "Context lost because MakeCurrent failed.";
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_buffer_->SetParseError(gpu::error::kLostContext);
3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CheckContextLost();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::Destroy() {
403c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (wait_for_token_) {
404c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Send(wait_for_token_->reply.release());
405c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    wait_for_token_.reset();
406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
407c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (wait_for_get_offset_) {
408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Send(wait_for_get_offset_->reply.release());
409c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    wait_for_get_offset_.reset();
410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (handle_.is_null() && !active_url_.is_empty()) {
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gpu_channel_manager->Send(new GpuHostMsg_DidDestroyOffscreenContext(
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        active_url_));
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memory_manager_client_state_.reset();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!sync_points_.empty())
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnRetireSyncPoint(sync_points_.front());
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (decoder_)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    decoder_->set_engine(NULL);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The scheduler has raw references to the decoder and the command buffer so
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destroy it before those.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_.reset();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool have_context = false;
4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (decoder_ && command_buffer_ &&
4315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      command_buffer_->GetLastState().error != gpu::error::kLostContext)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    have_context = decoder_->MakeCurrent();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(DestructionObserver,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    destruction_observers_,
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    OnWillDestroyStub());
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (decoder_) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decoder_->Destroy(have_context);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decoder_.reset();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_buffer_.reset();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // Remove this after crbug.com/248395 is sorted out.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  surface_ = NULL;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnInitializeFailed(IPC::Message* reply_message) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GpuCommandBufferMsg_Initialize::WriteReplyParams(
451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      reply_message, false, gpu::Capabilities());
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(reply_message);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnInitialize(
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::SharedMemoryHandle shared_state_handle,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::Message* reply_message) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnInitialize");
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!command_buffer_.get());
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::SharedMemory> shared_state_shm(
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::SharedMemory(shared_state_handle, false));
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_buffer_.reset(new gpu::CommandBufferService(
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_group_->transfer_buffer_manager()));
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool result = command_buffer_->Initialize();
468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(result);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group_.get()));
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(),
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         decoder_.get(),
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         decoder_.get()));
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (preemption_flag_.get())
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scheduler_->SetPreemptByFlag(preemption_flag_);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_->set_engine(scheduler_.get());
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handle_.is_null()) {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) || defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (software_) {
483c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      LOG(ERROR) << "No software support.";
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnInitializeFailed(reply_message);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    surface_ = ImageTransportSurface::CreateSurface(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channel_->gpu_channel_manager(),
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this,
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handle_);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuChannelManager* manager = channel_->gpu_channel_manager();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    surface_ = manager->GetDefaultOffscreenSurface();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!surface_.get()) {
499c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DLOG(ERROR) << "Failed to create surface.";
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnInitializeFailed(reply_message);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<gfx::GLContext> context;
50558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (use_virtualized_gl_context_ && channel_->share_group()) {
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context = channel_->share_group()->GetSharedContext();
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!context.get()) {
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      context = gfx::GLContext::CreateGLContext(
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          channel_->share_group(),
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          channel_->gpu_channel_manager()->GetDefaultOffscreenSurface(),
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gpu_preference_);
512c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (!context.get()) {
513c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        DLOG(ERROR) << "Failed to create shared context for virtualization.";
514c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        OnInitializeFailed(reply_message);
515c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return;
516c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      channel_->share_group()->SetSharedContext(context.get());
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This should be a non-virtual GL context.
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(context->GetHandle());
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    context = new gpu::GLContextVirtual(
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        channel_->share_group(), context.get(), decoder_->AsWeakPtr());
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!context->Initialize(surface_.get(), gpu_preference_)) {
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // TODO(sievers): The real context created above for the default
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // offscreen surface might not be compatible with this surface.
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Need to adjust at least GLX to be able to create the initial context
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // with a config that is compatible with onscreen and offscreen surfaces.
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      context = NULL;
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(ERROR) << "Failed to initialize virtual GL context.";
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnInitializeFailed(reply_message);
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!context.get()) {
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context = gfx::GLContext::CreateGLContext(
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        channel_->share_group(), surface_.get(), gpu_preference_);
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!context.get()) {
540c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DLOG(ERROR) << "Failed to create context.";
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnInitializeFailed(reply_message);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!context->MakeCurrent(surface_.get())) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to make context current.";
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnInitializeFailed(reply_message);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
551a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!context->GetGLStateRestorer()) {
552a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    context->SetGLStateRestorer(
553a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        new gpu::GLStateRestorerImpl(decoder_->AsWeakPtr()));
554a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
555a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!context->GetTotalGpuMemory(&total_gpu_memory_))
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    total_gpu_memory_ = 0;
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!context_group_->has_program_cache()) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_group_->set_program_cache(
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channel_->gpu_channel_manager()->program_cache());
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the decoder with either the view or pbuffer GLContext.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!decoder_->Initialize(surface_,
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            context,
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            !surface_id(),
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            initial_size_,
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            disallowed_features_,
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            requested_attribs_)) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Failed to initialize decoder.";
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnInitializeFailed(reply_message);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switches::kEnableGPUServiceLogging)) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decoder_->set_log_commands(true);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  decoder_->GetLogger()->SetMsgCallback(
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&GpuCommandBufferStub::SendConsoleMessage,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decoder_->SetShaderCacheCallback(
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&GpuCommandBufferStub::SendCachedShader,
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this)));
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decoder_->SetWaitSyncPointCallback(
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&GpuCommandBufferStub::OnWaitSyncPoint,
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(this)));
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_buffer_->SetPutOffsetChangeCallback(
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&GpuCommandBufferStub::PutChanged, base::Unretained(this)));
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_buffer_->SetGetBufferChangeCallback(
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&gpu::GpuScheduler::SetGetBuffer,
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(scheduler_.get())));
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_buffer_->SetParseErrorCallback(
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&GpuCommandBufferStub::OnParseError, base::Unretained(this)));
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scheduler_->SetSchedulingChangedCallback(
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&GpuChannel::StubSchedulingChanged,
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(channel_)));
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (watchdog_) {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scheduler_->SetCommandProcessedCallback(
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&GpuCommandBufferStub::OnCommandProcessed,
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
608e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState);
609e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!shared_state_shm->Map(kSharedStateSize)) {
610e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DLOG(ERROR) << "Failed to map shared state buffer.";
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnInitializeFailed(reply_message);
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
614e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  command_buffer_->SetSharedStateBuffer(gpu::MakeBackingFromSharedMemory(
615e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      shared_state_shm.Pass(), kSharedStateSize));
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
617116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gpu::Capabilities capabilities = decoder_->GetCapabilities();
618116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  capabilities.future_sync_points = channel_->allow_future_sync_points();
619116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
620a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GpuCommandBufferMsg_Initialize::WriteReplyParams(
621116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      reply_message, true, capabilities);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(reply_message);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (handle_.is_null() && !active_url_.is_empty()) {
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gpu_channel_manager->Send(new GpuHostMsg_DidCreateOffscreenContext(
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        active_url_));
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
631c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GpuCommandBufferStub::OnCreateStreamTexture(
632c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    uint32 texture_id, int32 stream_id, bool* succeeded) {
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID)
634c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *succeeded = StreamTexture::Create(this, texture_id, stream_id);
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else
636c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *succeeded = false;
6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GpuCommandBufferStub::SetLatencyInfoCallback(
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const LatencyInfoCallback& callback) {
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  latency_info_callback_ = callback;
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int32 GpuCommandBufferStub::GetRequestedAttribute(int attr) const {
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The command buffer is pairs of enum, value
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // search for the requested attribute, return the value.
648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (std::vector<int32>::const_iterator it = requested_attribs_.begin();
649f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != requested_attribs_.end(); ++it) {
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (*it++ == attr) {
651f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return *it;
652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
654f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return -1;
655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuCommandBufferStub::OnSetGetBuffer(int32 shm_id,
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          IPC::Message* reply_message) {
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetGetBuffer");
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (command_buffer_)
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    command_buffer_->SetGetBuffer(shm_id);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(reply_message);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void GpuCommandBufferStub::OnProduceFrontBuffer(const gpu::Mailbox& mailbox) {
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnProduceFrontBuffer");
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!decoder_) {
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LOG(ERROR) << "Can't produce front buffer before initialization.";
6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  decoder_->ProduceFrontBuffer(mailbox);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnParseError() {
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnParseError");
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(command_buffer_.get());
6785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gpu::CommandBuffer::State state = command_buffer_->GetLastState();
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Message* msg = new GpuCommandBufferMsg_Destroyed(
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      route_id_, state.context_lost_reason);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg->set_unblock(true);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(msg);
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Tell the browser about this context loss as well, so it can
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // determine whether client APIs like WebGL need to be immediately
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // blocked from automatically running.
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gpu_channel_manager->Send(new GpuHostMsg_DidLoseContext(
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      handle_.is_null(), state.context_lost_reason, active_url_));
6907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CheckContextLost();
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
694c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GpuCommandBufferStub::OnWaitForTokenInRange(int32 start,
695c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                 int32 end,
696c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                 IPC::Message* reply_message) {
697c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnWaitForTokenInRange");
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(command_buffer_.get());
6997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CheckContextLost();
700c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (wait_for_token_)
701c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR) << "Got WaitForToken command while currently waiting for token.";
702c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  wait_for_token_ =
703c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      make_scoped_ptr(new WaitForCommandState(start, end, reply_message));
704c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CheckCompleteWaits();
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
707c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GpuCommandBufferStub::OnWaitForGetOffsetInRange(
708c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int32 start,
709c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int32 end,
710c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IPC::Message* reply_message) {
711c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnWaitForGetOffsetInRange");
712c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(command_buffer_.get());
713c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CheckContextLost();
714c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (wait_for_get_offset_) {
715c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LOG(ERROR)
716c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        << "Got WaitForGetOffset command while currently waiting for offset.";
717c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
718c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  wait_for_get_offset_ =
719c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      make_scoped_ptr(new WaitForCommandState(start, end, reply_message));
720c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CheckCompleteWaits();
721c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
722c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
723c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GpuCommandBufferStub::CheckCompleteWaits() {
724c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (wait_for_token_ || wait_for_get_offset_) {
7255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    gpu::CommandBuffer::State state = command_buffer_->GetLastState();
726c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (wait_for_token_ &&
727c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        (gpu::CommandBuffer::InRange(
728c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch             wait_for_token_->start, wait_for_token_->end, state.token) ||
729c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         state.error != gpu::error::kNoError)) {
730c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ReportState();
731c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      GpuCommandBufferMsg_WaitForTokenInRange::WriteReplyParams(
732c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          wait_for_token_->reply.get(), state);
733c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      Send(wait_for_token_->reply.release());
734c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      wait_for_token_.reset();
735c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
736c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (wait_for_get_offset_ &&
737c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        (gpu::CommandBuffer::InRange(wait_for_get_offset_->start,
738c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     wait_for_get_offset_->end,
739c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     state.get_offset) ||
740c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         state.error != gpu::error::kNoError)) {
741c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ReportState();
742c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      GpuCommandBufferMsg_WaitForGetOffsetInRange::WriteReplyParams(
743c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          wait_for_get_offset_->reply.get(), state);
744c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      Send(wait_for_get_offset_->reply.release());
745c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      wait_for_get_offset_.reset();
746c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
747c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
748c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
749c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
7501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GpuCommandBufferStub::OnAsyncFlush(
7511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int32 put_offset,
7521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    uint32 flush_count,
7531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::vector<ui::LatencyInfo>& latency_info) {
754c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  TRACE_EVENT1(
755c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "gpu", "GpuCommandBufferStub::OnAsyncFlush", "put_offset", put_offset);
7561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (ui::LatencyInfo::Verify(latency_info,
7581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              "GpuCommandBufferStub::OnAsyncFlush") &&
7591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !latency_info_callback_.is_null()) {
7601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    latency_info_callback_.Run(latency_info);
7611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(command_buffer_.get());
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (flush_count - last_flush_count_ < 0x8000000U) {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_flush_count_ = flush_count;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_buffer_->Flush(put_offset);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We received this message out-of-order. This should not happen but is here
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to catch regressions. Ignore the message.
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Received a Flush message out-of-order";
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportState();
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnRescheduled() {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu::CommandBuffer::State pre_state = command_buffer_->GetLastState();
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_buffer_->Flush(pre_state.put_offset);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gpu::CommandBuffer::State post_state = command_buffer_->GetLastState();
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pre_state.get_offset != post_state.get_offset)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportState();
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnRegisterTransferBuffer(
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32 id,
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle transfer_buffer,
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32 size) {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterTransferBuffer");
789effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
790effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Take ownership of the memory and map it into this process.
791effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // This validates the size.
792effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  scoped_ptr<base::SharedMemory> shared_memory(
793effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      new base::SharedMemory(transfer_buffer, false));
794effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!shared_memory->Map(size)) {
795effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DVLOG(0) << "Failed to map shared memory.";
796effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
797effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
799e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (command_buffer_) {
800e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    command_buffer_->RegisterTransferBuffer(
801e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        id, gpu::MakeBackingFromSharedMemory(shared_memory.Pass(), size));
802e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuCommandBufferStub::OnDestroyTransferBuffer(int32 id) {
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyTransferBuffer");
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (command_buffer_)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_buffer_->DestroyTransferBuffer(id);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnCommandProcessed() {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (watchdog_)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    watchdog_->CheckArmed();
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
817c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GpuCommandBufferStub::ReportState() { command_buffer_->UpdateState(); }
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::PutChanged() {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FastSetActiveURL(active_url_, active_url_hash_);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_->PutChanged();
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnCreateVideoDecoder(
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoCodecProfile profile,
826c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int32 decoder_route_id,
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::Message* reply_message) {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateVideoDecoder");
82958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  GpuVideoDecodeAccelerator* decoder = new GpuVideoDecodeAccelerator(
83058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      decoder_route_id, this, channel_->io_message_loop());
83158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  decoder->Initialize(profile, reply_message);
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // decoder is registered as a DestructionObserver of this stub and will
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // self-delete during destruction of this stub.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
836c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GpuCommandBufferStub::OnCreateVideoEncoder(
837c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    media::VideoFrame::Format input_format,
838c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const gfx::Size& input_visible_size,
839c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    media::VideoCodecProfile output_profile,
840c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    uint32 initial_bitrate,
841c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int32 encoder_route_id,
842c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IPC::Message* reply_message) {
843c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateVideoEncoder");
844c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  GpuVideoEncodeAccelerator* encoder =
845c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new GpuVideoEncodeAccelerator(encoder_route_id, this);
846c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  encoder->Initialize(input_format,
847c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      input_visible_size,
848c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      output_profile,
849c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      initial_bitrate,
850c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      reply_message);
851c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // encoder is registered as a DestructionObserver of this stub and will
852c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // self-delete during destruction of this stub.
853c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
854c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnSetSurfaceVisible(bool visible) {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetSurfaceVisible");
857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (memory_manager_client_state_)
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    memory_manager_client_state_->SetVisible(visible);
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::AddSyncPoint(uint32 sync_point) {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_points_.push_back(sync_point);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnRetireSyncPoint(uint32 sync_point) {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!sync_points_.empty() && sync_points_.front() == sync_point);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_points_.pop_front();
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuChannelManager* manager = channel_->gpu_channel_manager();
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager->sync_point_manager()->RetireSyncPoint(sync_point);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GpuCommandBufferStub::OnWaitSyncPoint(uint32 sync_point) {
873a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!sync_point)
874a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return true;
8755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GpuChannelManager* manager = channel_->gpu_channel_manager();
8765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (manager->sync_point_manager()->IsSyncPointRetired(sync_point))
8775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
8785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sync_point_wait_count_ == 0) {
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN1("gpu", "WaitSyncPoint", this,
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "GpuCommandBufferStub", this);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scheduler_->SetScheduled(false);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++sync_point_wait_count_;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager->sync_point_manager()->AddSyncPointCallback(
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_point,
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&GpuCommandBufferStub::OnSyncPointRetired,
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 this->AsWeakPtr()));
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return scheduler_->IsScheduled();
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnSyncPointRetired() {
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --sync_point_wait_count_;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sync_point_wait_count_ == 0) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_EVENT_ASYNC_END1("gpu", "WaitSyncPoint", this,
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "GpuCommandBufferStub", this);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scheduler_->SetScheduled(true);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnSignalSyncPoint(uint32 sync_point, uint32 id) {
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuChannelManager* manager = channel_->gpu_channel_manager();
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager->sync_point_manager()->AddSyncPointCallback(
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_point,
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&GpuCommandBufferStub::OnSignalSyncPointAck,
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 this->AsWeakPtr(),
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 id));
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnSignalSyncPointAck(uint32 id) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuCommandBufferMsg_SignalSyncPointAck(route_id_, id));
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid GpuCommandBufferStub::OnSignalQuery(uint32 query_id, uint32 id) {
915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (decoder_) {
916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gpu::gles2::QueryManager* query_manager = decoder_->GetQueryManager();
917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (query_manager) {
918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      gpu::gles2::QueryManager::Query* query =
919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          query_manager->GetQuery(query_id);
920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (query) {
921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        query->AddCallback(
922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::Bind(&GpuCommandBufferStub::OnSignalSyncPointAck,
923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     this->AsWeakPtr(),
924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     id));
925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return;
926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Something went wrong, run callback immediately.
930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnSignalSyncPointAck(id);
931eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::OnSetClientHasMemoryAllocationChangedCallback(
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_callback) {
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0(
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "gpu",
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "GpuCommandBufferStub::OnSetClientHasMemoryAllocationChangedCallback");
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_callback) {
940c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!memory_manager_client_state_) {
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      memory_manager_client_state_.reset(GetMemoryManager()->CreateClientState(
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          this, surface_id_ != 0, true));
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    memory_manager_client_state_.reset();
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void GpuCommandBufferStub::OnRegisterGpuMemoryBuffer(
9501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int32 id,
9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gfx::GpuMemoryBufferHandle handle,
9521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    uint32 width,
9531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    uint32 height,
9541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    uint32 internalformat) {
9551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterGpuMemoryBuffer");
9564ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch#if defined(OS_ANDROID)
9574ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Verify that renderer is not trying to use a surface texture it doesn't own.
9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (handle.type == gfx::SURFACE_TEXTURE_BUFFER &&
9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      handle.surface_texture_id.secondary_id != channel()->client_id()) {
9604ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    LOG(ERROR) << "Illegal surface texture ID for renderer.";
9614ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    return;
9624ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
9634ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch#endif
9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!decoder_)
9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(image_manager);
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (image_manager->LookupImage(id)) {
9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Image already exists with same ID.";
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
9731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GpuChannelManager* manager = channel_->gpu_channel_manager();
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<gfx::GLImage> image =
9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      manager->gpu_memory_buffer_factory()->CreateImageForGpuMemoryBuffer(
9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          handle,
9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          gfx::Size(width, height),
9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          internalformat,
9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          channel()->client_id());
9821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!image.get())
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // For Android specific workaround.
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (context_group_->feature_info()->workarounds().release_image_after_use)
9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    image->SetReleaseAfterUse();
9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  image_manager->AddImage(image.get(), id);
9901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
9911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GpuCommandBufferStub::OnUnregisterGpuMemoryBuffer(int32 id) {
9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnUnregisterGpuMemoryBuffer");
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!decoder_)
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(image_manager);
10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!image_manager->LookupImage(id)) {
10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Image with ID doesn't exist.";
10025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  image_manager->RemoveImage(id);
10061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
10071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::SendConsoleMessage(
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 id,
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& message) {
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GPUCommandBufferConsoleMessage console_message;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  console_message.id = id;
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  console_message.message = message;
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Message* msg = new GpuCommandBufferMsg_ConsoleMsg(
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      route_id_, console_message);
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg->set_unblock(true);
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(msg);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuCommandBufferStub::SendCachedShader(
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& key, const std::string& shader) {
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  channel_->CacheShader(key, shader);
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::AddDestructionObserver(
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestructionObserver* observer) {
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  destruction_observers_.AddObserver(observer);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::RemoveDestructionObserver(
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestructionObserver* observer) {
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  destruction_observers_.RemoveObserver(observer);
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuCommandBufferStub::SetPreemptByFlag(
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<gpu::PreemptionFlag> flag) {
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  preemption_flag_ = flag;
1038c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (scheduler_)
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scheduler_->SetPreemptByFlag(preemption_flag_);
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GpuCommandBufferStub::GetTotalGpuMemory(uint64* bytes) {
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *bytes = total_gpu_memory_;
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !!total_gpu_memory_;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size GpuCommandBufferStub::GetSurfaceSize() const {
1048868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!surface_.get())
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gfx::Size();
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return surface_->GetSize();
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gpu::gles2::MemoryTracker* GpuCommandBufferStub::GetMemoryTracker() const {
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_group_->memory_tracker();
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuCommandBufferStub::SetMemoryAllocation(
10581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const gpu::MemoryAllocation& allocation) {
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!last_memory_allocation_valid_ ||
10601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      !allocation.Equals(last_memory_allocation_)) {
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Send(new GpuCommandBufferMsg_SetMemoryAllocation(
10621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        route_id_, allocation));
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_memory_allocation_valid_ = true;
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_memory_allocation_ = allocation;
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void GpuCommandBufferStub::SuggestHaveFrontBuffer(
10701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    bool suggest_have_frontbuffer) {
10711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // This can be called outside of OnMessageReceived, so the context needs
10721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // to be made current before calling methods on the surface.
10731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (surface_.get() && MakeCurrent())
10741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    surface_->SetFrontbufferAllocation(suggest_have_frontbuffer);
10751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
10761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
10777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool GpuCommandBufferStub::CheckContextLost() {
10787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(command_buffer_);
10795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gpu::CommandBuffer::State state = command_buffer_->GetLastState();
10807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool was_lost = state.error == gpu::error::kLostContext;
10817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Lose all other contexts if the reset was triggered by the robustness
10827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // extension instead of being synthetic.
10837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (was_lost && decoder_ && decoder_->WasContextLostByRobustnessExtension() &&
10847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      (gfx::GLContext::LosesAllContextsOnContextLost() ||
10857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       use_virtualized_gl_context_))
10867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    channel_->LoseAllContexts();
1087c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CheckCompleteWaits();
10887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return was_lost;
10897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
10907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid GpuCommandBufferStub::MarkContextLost() {
10927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!command_buffer_ ||
10935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      command_buffer_->GetLastState().error == gpu::error::kLostContext)
10947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
10957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
10967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  command_buffer_->SetContextLostReason(gpu::error::kUnknown);
10977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (decoder_)
10987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    decoder_->LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
10997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  command_buffer_->SetParseError(gpu::error::kLostContext);
11007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
11017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)uint64 GpuCommandBufferStub::GetMemoryUsage() const {
1103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return GetMemoryManager()->GetClientMemoryUsage(this);
1104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
1107