1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "gpu/command_buffer/service/async_pixel_transfer_manager_idle.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/trace_event.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h"
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/memory/weak_ptr.h"
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "gpu/command_buffer/service/safe_shared_memory_pool.h"
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "ui/gl/scoped_binders.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace gpu {
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::LazyInstance<SafeSharedMemoryPool> g_safe_shared_memory_pool =
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SafeSharedMemoryPool* safe_shared_memory_pool() {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_safe_shared_memory_pool.Pointer();
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static uint64 g_next_pixel_transfer_state_id = 1;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PerformNotifyCompletion(
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    AsyncMemoryParams mem_params,
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ScopedSafeSharedMemory* safe_shared_memory,
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_refptr<AsyncPixelTransferCompletionObserver> observer) {
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TRACE_EVENT0("gpu", "PerformNotifyCompletion");
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AsyncMemoryParams safe_mem_params = mem_params;
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  safe_mem_params.shared_memory = safe_shared_memory->shared_memory();
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  observer->DidComplete(safe_mem_params);
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Class which handles async pixel transfers in a platform
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// independent way.
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class AsyncPixelTransferDelegateIdle
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : public AsyncPixelTransferDelegate,
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      public base::SupportsWeakPtr<AsyncPixelTransferDelegateIdle> {
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AsyncPixelTransferDelegateIdle(
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      AsyncPixelTransferManagerIdle::SharedState* state,
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      GLuint texture_id,
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const AsyncTexImage2DParams& define_params);
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual ~AsyncPixelTransferDelegateIdle();
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Implement AsyncPixelTransferDelegate:
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void AsyncTexImage2D(
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const AsyncTexImage2DParams& tex_params,
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const AsyncMemoryParams& mem_params,
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const base::Closure& bind_callback) OVERRIDE;
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void AsyncTexSubImage2D(
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const AsyncTexSubImage2DParams& tex_params,
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const AsyncMemoryParams& mem_params) OVERRIDE;
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  virtual bool TransferIsInProgress() OVERRIDE;
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  virtual void WaitForTransferCompletion() OVERRIDE;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void PerformAsyncTexImage2D(
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      AsyncTexImage2DParams tex_params,
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      AsyncMemoryParams mem_params,
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const base::Closure& bind_callback,
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ScopedSafeSharedMemory* safe_shared_memory);
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void PerformAsyncTexSubImage2D(
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      AsyncTexSubImage2DParams tex_params,
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      AsyncMemoryParams mem_params,
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ScopedSafeSharedMemory* safe_shared_memory);
727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  uint64 id_;
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  GLuint texture_id_;
757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bool transfer_in_progress_;
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AsyncTexImage2DParams define_params_;
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Safe to hold a raw pointer because SharedState is owned by the Manager
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // which owns the Delegate.
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AsyncPixelTransferManagerIdle::SharedState* shared_state_;
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateIdle);
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AsyncPixelTransferDelegateIdle::AsyncPixelTransferDelegateIdle(
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AsyncPixelTransferManagerIdle::SharedState* shared_state,
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    GLuint texture_id,
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const AsyncTexImage2DParams& define_params)
897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : id_(g_next_pixel_transfer_state_id++),
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      texture_id_(texture_id),
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      transfer_in_progress_(false),
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      define_params_(define_params),
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      shared_state_(shared_state) {}
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AsyncPixelTransferDelegateIdle::~AsyncPixelTransferDelegateIdle() {}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AsyncPixelTransferDelegateIdle::AsyncTexImage2D(
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AsyncTexImage2DParams& tex_params,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AsyncMemoryParams& mem_params,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& bind_callback) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(mem_params.shared_memory);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mem_params.shm_size);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task(
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      id_,
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          &AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D,
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          AsWeakPtr(),
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          tex_params,
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          mem_params,
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          bind_callback,
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                                 mem_params.shared_memory,
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                                 mem_params.shm_size)))));
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  transfer_in_progress_ = true;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AsyncPixelTransferDelegateIdle::AsyncTexSubImage2D(
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AsyncTexSubImage2DParams& tex_params,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AsyncMemoryParams& mem_params) {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(mem_params.shared_memory);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mem_params.shm_size);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task(
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      id_,
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          &AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D,
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          AsWeakPtr(),
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          tex_params,
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          mem_params,
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                                 mem_params.shared_memory,
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                                 mem_params.shm_size)))));
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  transfer_in_progress_ = true;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool  AsyncPixelTransferDelegateIdle::TransferIsInProgress() {
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return transfer_in_progress_;
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AsyncPixelTransferDelegateIdle::WaitForTransferCompletion() {
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (std::list<AsyncPixelTransferManagerIdle::Task>::iterator iter =
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           shared_state_->tasks.begin();
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       iter != shared_state_->tasks.end();
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       ++iter) {
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (iter->transfer_id != id_)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*iter).task.Run();
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    shared_state_->tasks.erase(iter);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    break;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_->ProcessNotificationTasks();
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D(
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AsyncTexImage2DParams tex_params,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AsyncMemoryParams mem_params,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& bind_callback,
1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ScopedSafeSharedMemory* safe_shared_memory) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT2("gpu", "PerformAsyncTexImage2D",
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               "width", tex_params.width,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               "height", tex_params.height);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  void* data = GetAddress(safe_shared_memory, mem_params);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::TimeTicks begin_time(base::TimeTicks::HighResNow());
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_EVENT0("gpu", "glTexImage2D");
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    glTexImage2D(
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.target,
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.level,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.internal_format,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.width,
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.height,
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.border,
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.format,
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.type,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        data);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  transfer_in_progress_ = false;
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  shared_state_->texture_upload_count++;
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  shared_state_->total_texture_upload_time +=
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::TimeTicks::HighResNow() - begin_time;
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The texture is already fully bound so just call it now.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bind_callback.Run();
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D(
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AsyncTexSubImage2DParams tex_params,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AsyncMemoryParams mem_params,
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ScopedSafeSharedMemory* safe_shared_memory) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D",
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               "width", tex_params.width,
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               "height", tex_params.height);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
208a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  void* data = GetAddress(safe_shared_memory, mem_params);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeTicks begin_time(base::TimeTicks::HighResNow());
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If it's a full texture update, use glTexImage2D as it's faster.
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // TODO(epenner): Make this configurable (http://crbug.com/259924)
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (tex_params.xoffset == 0 &&
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      tex_params.yoffset == 0 &&
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      tex_params.target == define_params_.target &&
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      tex_params.level  == define_params_.level &&
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      tex_params.width  == define_params_.width &&
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      tex_params.height == define_params_.height) {
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TRACE_EVENT0("gpu", "glTexImage2D");
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    glTexImage2D(
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        define_params_.target,
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        define_params_.level,
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        define_params_.internal_format,
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        define_params_.width,
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        define_params_.height,
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        define_params_.border,
2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        tex_params.format,
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        tex_params.type,
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        data);
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_EVENT0("gpu", "glTexSubImage2D");
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    glTexSubImage2D(
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.target,
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.level,
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.xoffset,
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.yoffset,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.width,
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.height,
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.format,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tex_params.type,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        data);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  transfer_in_progress_ = false;
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_->texture_upload_count++;
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_->total_texture_upload_time +=
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::TimeTicks::HighResNow() - begin_time;
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AsyncPixelTransferManagerIdle::Task::Task(
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    uint64 transfer_id, const base::Closure& task)
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : transfer_id(transfer_id),
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      task(task) {
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AsyncPixelTransferManagerIdle::Task::~Task() {}
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AsyncPixelTransferManagerIdle::SharedState::SharedState()
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : texture_upload_count(0) {}
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AsyncPixelTransferManagerIdle::SharedState::~SharedState() {}
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AsyncPixelTransferManagerIdle::SharedState::ProcessNotificationTasks() {
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  while (!tasks.empty()) {
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Stop when we reach a pixel transfer task.
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (tasks.front().transfer_id)
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    tasks.front().task.Run();
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    tasks.pop_front();
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AsyncPixelTransferManagerIdle::AsyncPixelTransferManagerIdle()
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  : shared_state_() {
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AsyncPixelTransferManagerIdle::~AsyncPixelTransferManagerIdle() {}
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AsyncPixelTransferManagerIdle::BindCompletedAsyncTransfers() {
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Everything is already bound.
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AsyncPixelTransferManagerIdle::AsyncNotifyCompletion(
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const AsyncMemoryParams& mem_params,
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    AsyncPixelTransferCompletionObserver* observer) {
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (shared_state_.tasks.empty()) {
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    observer->DidComplete(mem_params);
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_.tasks.push_back(
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Task(0,  // 0 transfer_id for notification tasks.
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           base::Bind(
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               &PerformNotifyCompletion,
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               mem_params,
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                      mem_params.shared_memory,
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                      mem_params.shm_size)),
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch               make_scoped_refptr(observer))));
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)uint32 AsyncPixelTransferManagerIdle::GetTextureUploadCount() {
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return shared_state_.texture_upload_count;
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::TimeDelta AsyncPixelTransferManagerIdle::GetTotalTextureUploadTime() {
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return shared_state_.total_texture_upload_time;
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AsyncPixelTransferManagerIdle::ProcessMorePendingTransfers() {
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (shared_state_.tasks.empty())
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // First task should always be a pixel transfer task.
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(shared_state_.tasks.front().transfer_id);
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_.tasks.front().task.Run();
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_.tasks.pop_front();
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shared_state_.ProcessNotificationTasks();
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool AsyncPixelTransferManagerIdle::NeedsProcessMorePendingTransfers() {
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !shared_state_.tasks.empty();
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AsyncPixelTransferDelegate*
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)AsyncPixelTransferManagerIdle::CreatePixelTransferDelegateImpl(
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gles2::TextureRef* ref,
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const AsyncTexImage2DParams& define_params) {
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return new AsyncPixelTransferDelegateIdle(&shared_state_,
3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                            ref->service_id(),
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                            define_params);
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace gpu
339