1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_COMMON_GPU_CLIENT_WEBGRAPHICSCONTEXT3D_COMMAND_BUFFER_IMPL_H_
6#define CONTENT_COMMON_GPU_CLIENT_WEBGRAPHICSCONTEXT3D_COMMAND_BUFFER_IMPL_H_
7
8#include <string>
9#include <vector>
10
11#include "base/callback.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/memory/weak_ptr.h"
14#include "base/synchronization/lock.h"
15#include "content/common/content_export.h"
16#include "content/common/gpu/client/command_buffer_proxy_impl.h"
17#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
18#include "third_party/WebKit/public/platform/WebString.h"
19#include "ui/gfx/native_widget_types.h"
20#include "ui/gl/gpu_preference.h"
21#include "url/gurl.h"
22#include "webkit/common/gpu/webgraphicscontext3d_impl.h"
23
24namespace gpu {
25
26class ContextSupport;
27class TransferBuffer;
28
29namespace gles2 {
30class GLES2CmdHelper;
31class GLES2Implementation;
32class GLES2Interface;
33}
34}
35
36namespace content {
37class GpuChannelHost;
38
39const size_t kDefaultCommandBufferSize = 1024 * 1024;
40const size_t kDefaultStartTransferBufferSize = 1 * 1024 * 1024;
41const size_t kDefaultMinTransferBufferSize = 1 * 256 * 1024;
42const size_t kDefaultMaxTransferBufferSize = 16 * 1024 * 1024;
43
44class WebGraphicsContext3DCommandBufferImpl
45    : public webkit::gpu::WebGraphicsContext3DImpl {
46 public:
47  enum MappedMemoryReclaimLimit {
48    kNoLimit = 0,
49  };
50
51  struct CONTENT_EXPORT SharedMemoryLimits {
52    SharedMemoryLimits();
53
54    size_t command_buffer_size;
55    size_t start_transfer_buffer_size;
56    size_t min_transfer_buffer_size;
57    size_t max_transfer_buffer_size;
58    size_t mapped_memory_reclaim_limit;
59  };
60
61  class ShareGroup : public base::RefCountedThreadSafe<ShareGroup> {
62   public:
63    ShareGroup();
64
65    WebGraphicsContext3DCommandBufferImpl* GetAnyContextLocked() {
66      // In order to ensure that the context returned is not removed while
67      // in use, the share group's lock should be aquired before calling this
68      // function.
69      lock_.AssertAcquired();
70      if (contexts_.empty())
71        return NULL;
72      return contexts_.front();
73    }
74
75    void AddContextLocked(WebGraphicsContext3DCommandBufferImpl* context) {
76      lock_.AssertAcquired();
77      contexts_.push_back(context);
78    }
79
80    void RemoveContext(WebGraphicsContext3DCommandBufferImpl* context) {
81      base::AutoLock auto_lock(lock_);
82      contexts_.erase(std::remove(contexts_.begin(), contexts_.end(), context),
83          contexts_.end());
84    }
85
86    void RemoveAllContexts() {
87      base::AutoLock auto_lock(lock_);
88      contexts_.clear();
89    }
90
91    base::Lock& lock() {
92      return lock_;
93    }
94
95   private:
96    friend class base::RefCountedThreadSafe<ShareGroup>;
97    virtual ~ShareGroup();
98
99    std::vector<WebGraphicsContext3DCommandBufferImpl*> contexts_;
100    base::Lock lock_;
101
102    DISALLOW_COPY_AND_ASSIGN(ShareGroup);
103  };
104
105  WebGraphicsContext3DCommandBufferImpl(
106      int surface_id,
107      const GURL& active_url,
108      GpuChannelHost* host,
109      const Attributes& attributes,
110      bool lose_context_when_out_of_memory,
111      const SharedMemoryLimits& limits,
112      WebGraphicsContext3DCommandBufferImpl* share_context);
113
114  virtual ~WebGraphicsContext3DCommandBufferImpl();
115
116  CommandBufferProxyImpl* GetCommandBufferProxy() {
117    return command_buffer_.get();
118  }
119
120  CONTENT_EXPORT gpu::ContextSupport* GetContextSupport();
121
122  gpu::gles2::GLES2Implementation* GetImplementation() {
123    return real_gl_.get();
124  }
125
126  // Return true if GPU process reported context lost or there was a
127  // problem communicating with the GPU process.
128  bool IsCommandBufferContextLost();
129
130  // Create & initialize a WebGraphicsContext3DCommandBufferImpl.  Return NULL
131  // on any failure.
132  static CONTENT_EXPORT WebGraphicsContext3DCommandBufferImpl*
133      CreateOffscreenContext(
134          GpuChannelHost* host,
135          const WebGraphicsContext3D::Attributes& attributes,
136          bool lose_context_when_out_of_memory,
137          const GURL& active_url,
138          const SharedMemoryLimits& limits,
139          WebGraphicsContext3DCommandBufferImpl* share_context);
140
141  size_t GetMappedMemoryLimit() {
142    return mem_limits_.mapped_memory_reclaim_limit;
143  }
144
145  // WebGraphicsContext3DImpl methods
146  virtual bool InitializeOnCurrentThread() OVERRIDE;
147
148  //----------------------------------------------------------------------
149  // WebGraphicsContext3D methods
150  virtual bool isContextLost();
151
152  virtual WGC3Denum getGraphicsResetStatusARB();
153
154 private:
155  // These are the same error codes as used by EGL.
156  enum Error {
157    SUCCESS               = 0x3000,
158    BAD_ATTRIBUTE         = 0x3004,
159    CONTEXT_LOST          = 0x300E
160  };
161
162  // Initialize the underlying GL context. May be called multiple times; second
163  // and subsequent calls are ignored. Must be called from the thread that is
164  // going to use this object to issue GL commands (which might not be the main
165  // thread).
166  bool MaybeInitializeGL();
167
168  bool InitializeCommandBuffer(bool onscreen,
169      WebGraphicsContext3DCommandBufferImpl* share_context);
170
171  void Destroy();
172
173  // Create a CommandBufferProxy that renders directly to a view. The view and
174  // the associated window must not be destroyed until the returned
175  // CommandBufferProxy has been destroyed, otherwise the GPU process might
176  // attempt to render to an invalid window handle.
177  //
178  // NOTE: on Mac OS X, this entry point is only used to set up the
179  // accelerated compositor's output. On this platform, we actually pass
180  // a gfx::PluginWindowHandle in place of the gfx::NativeViewId,
181  // because the facility to allocate a fake PluginWindowHandle is
182  // already in place. We could add more entry points and messages to
183  // allocate both fake PluginWindowHandles and NativeViewIds and map
184  // from fake NativeViewIds to PluginWindowHandles, but this seems like
185  // unnecessary complexity at the moment.
186  bool CreateContext(bool onscreen);
187
188  virtual void OnGpuChannelLost();
189
190  bool lose_context_when_out_of_memory_;
191  blink::WebGraphicsContext3D::Attributes attributes_;
192
193  bool visible_;
194
195  // State needed by MaybeInitializeGL.
196  scoped_refptr<GpuChannelHost> host_;
197  int32 surface_id_;
198  GURL active_url_;
199
200  gfx::GpuPreference gpu_preference_;
201
202  scoped_ptr<CommandBufferProxyImpl> command_buffer_;
203  scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_helper_;
204  scoped_ptr<gpu::TransferBuffer> transfer_buffer_;
205  scoped_ptr<gpu::gles2::GLES2Implementation> real_gl_;
206  scoped_ptr<gpu::gles2::GLES2Interface> trace_gl_;
207  Error last_error_;
208  SharedMemoryLimits mem_limits_;
209  scoped_refptr<ShareGroup> share_group_;
210
211  // Member variables should appear before the WeakPtrFactory, to ensure
212  // that any WeakPtrs to Controller are invalidated before its members
213  // variable's destructors are executed, rendering them invalid.
214  base::WeakPtrFactory<WebGraphicsContext3DCommandBufferImpl> weak_ptr_factory_;
215};
216
217}  // namespace content
218
219#endif  // CONTENT_COMMON_GPU_CLIENT_WEBGRAPHICSCONTEXT3D_COMMAND_BUFFER_IMPL_H_
220