Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: ppapi/proxy/ppb_graphics_3d_proxy.cc

Issue 24466004: PPAPI: Make GLES2 calls resilient to bad/dead resources. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/ppb_graphics_3d_proxy.h ('k') | ppapi/shared_impl/ppb_graphics_3d_shared.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/ppb_graphics_3d_proxy.h" 5 #include "ppapi/proxy/ppb_graphics_3d_proxy.h"
6 6
7 #include "gpu/command_buffer/client/gles2_implementation.h" 7 #include "gpu/command_buffer/client/gles2_implementation.h"
8 #include "gpu/command_buffer/common/command_buffer.h" 8 #include "gpu/command_buffer/common/command_buffer.h"
9 #include "ppapi/c/pp_errors.h" 9 #include "ppapi/c/pp_errors.h"
10 #include "ppapi/proxy/enter_proxy.h" 10 #include "ppapi/proxy/enter_proxy.h"
11 #include "ppapi/proxy/plugin_dispatcher.h" 11 #include "ppapi/proxy/plugin_dispatcher.h"
12 #include "ppapi/proxy/ppapi_command_buffer_proxy.h" 12 #include "ppapi/proxy/ppapi_command_buffer_proxy.h"
13 #include "ppapi/proxy/ppapi_messages.h" 13 #include "ppapi/proxy/ppapi_messages.h"
14 #include "ppapi/shared_impl/ppapi_globals.h" 14 #include "ppapi/shared_impl/ppapi_globals.h"
15 #include "ppapi/shared_impl/proxy_lock.h"
16 #include "ppapi/thunk/enter.h" 15 #include "ppapi/thunk/enter.h"
17 #include "ppapi/thunk/resource_creation_api.h" 16 #include "ppapi/thunk/resource_creation_api.h"
18 #include "ppapi/thunk/thunk.h" 17 #include "ppapi/thunk/thunk.h"
19 18
20 using ppapi::thunk::EnterResourceNoLock; 19 using ppapi::thunk::EnterResourceNoLock;
21 using ppapi::thunk::PPB_Graphics3D_API; 20 using ppapi::thunk::PPB_Graphics3D_API;
22 using ppapi::thunk::ResourceCreationAPI; 21 using ppapi::thunk::ResourceCreationAPI;
23 22
24 namespace ppapi { 23 namespace ppapi {
25 namespace proxy { 24 namespace proxy {
(...skipping 20 matching lines...) Expand all
46 } 45 }
47 46
48 gpu::CommandBuffer::State GetErrorState() { 47 gpu::CommandBuffer::State GetErrorState() {
49 gpu::CommandBuffer::State error_state; 48 gpu::CommandBuffer::State error_state;
50 error_state.error = gpu::error::kGenericError; 49 error_state.error = gpu::error::kGenericError;
51 return error_state; 50 return error_state;
52 } 51 }
53 52
54 } // namespace 53 } // namespace
55 54
56 // This class just wraps a CommandBuffer and optionally locks around every
57 // method. This is used to ensure that we have the Proxy lock any time we enter
58 // PpapiCommandBufferProxy.
59 //
60 // Note, for performance reasons, most of this code is not truly thread
61 // safe in the sense of multiple threads concurrently rendering to the same
62 // Graphics3D context; this isn't allowed, and will likely either crash or
63 // result in undefined behavior. It is assumed that the thread which creates
64 // the Graphics3D context will be the thread on which subsequent gl rendering
65 // will be done. This is why it is okay to read need_to_lock_ without the lock;
66 // it should only ever be read and written on the same thread where the context
67 // was created.
68 //
69 // TODO(nfullagar): At some point, allow multiple threads to concurrently render
70 // each to its own context. First step is to allow a single thread (either main
71 // thread or background thread) to render to a single Graphics3D context.
72 class Graphics3D::LockingCommandBuffer : public gpu::CommandBuffer {
73 public:
74 explicit LockingCommandBuffer(gpu::CommandBuffer* gpu_command_buffer)
75 : gpu_command_buffer_(gpu_command_buffer), need_to_lock_(true) {
76 }
77 virtual ~LockingCommandBuffer() {
78 }
79 void set_need_to_lock(bool need_to_lock) { need_to_lock_ = need_to_lock; }
80 bool need_to_lock() const { return need_to_lock_; }
81
82 private:
83 // MaybeLock acquires the proxy lock on construction if and only if
84 // need_to_lock is true. If it acquired the lock, it releases it on
85 // destruction. If need_to_lock is false, then the lock must already be held.
86 struct MaybeLock {
87 explicit MaybeLock(bool need_to_lock) : locked_(need_to_lock) {
88 if (need_to_lock)
89 ppapi::ProxyLock::Acquire();
90 else
91 ppapi::ProxyLock::AssertAcquired();
92 }
93 ~MaybeLock() {
94 if (locked_)
95 ppapi::ProxyLock::Release();
96 }
97 private:
98 bool locked_;
99 };
100
101 // gpu::CommandBuffer implementation:
102 virtual bool Initialize() OVERRIDE {
103 MaybeLock lock(need_to_lock_);
104 return gpu_command_buffer_->Initialize();
105 }
106 virtual State GetState() OVERRIDE {
107 MaybeLock lock(need_to_lock_);
108 return gpu_command_buffer_->GetState();
109 }
110 virtual State GetLastState() OVERRIDE {
111 // During a normal scene, the vast majority of calls are to GetLastState().
112 // We don't allow multi-threaded rendering on the same contex, so for
113 // performance reasons, avoid the global lock for this entry point. We can
114 // get away with this here because the underlying implementation of
115 // GetLastState() is trivial and does not involve global or shared state
116 // between other contexts.
117 // TODO(nfullagar): We can probably skip MaybeLock for other methods, but
118 // the performance gain may not be worth it.
119 //
120 // MaybeLock lock(need_to_lock_);
121 return gpu_command_buffer_->GetLastState();
122 }
123 virtual int32 GetLastToken() OVERRIDE {
124 return GetLastState().token;
125 }
126 virtual void Flush(int32 put_offset) OVERRIDE {
127 MaybeLock lock(need_to_lock_);
128 gpu_command_buffer_->Flush(put_offset);
129 }
130 virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE {
131 MaybeLock lock(need_to_lock_);
132 return gpu_command_buffer_->FlushSync(put_offset, last_known_get);
133 }
134 virtual void SetGetBuffer(int32 transfer_buffer_id) OVERRIDE {
135 MaybeLock lock(need_to_lock_);
136 gpu_command_buffer_->SetGetBuffer(transfer_buffer_id);
137 }
138 virtual void SetGetOffset(int32 get_offset) OVERRIDE {
139 MaybeLock lock(need_to_lock_);
140 gpu_command_buffer_->SetGetOffset(get_offset);
141 }
142 virtual gpu::Buffer CreateTransferBuffer(size_t size,
143 int32* id) OVERRIDE {
144 MaybeLock lock(need_to_lock_);
145 return gpu_command_buffer_->CreateTransferBuffer(size, id);
146 }
147 virtual void DestroyTransferBuffer(int32 id) OVERRIDE {
148 MaybeLock lock(need_to_lock_);
149 gpu_command_buffer_->DestroyTransferBuffer(id);
150 }
151 virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE {
152 MaybeLock lock(need_to_lock_);
153 return gpu_command_buffer_->GetTransferBuffer(id);
154 }
155 virtual void SetToken(int32 token) OVERRIDE {
156 MaybeLock lock(need_to_lock_);
157 gpu_command_buffer_->SetToken(token);
158 }
159 virtual void SetParseError(gpu::error::Error error) OVERRIDE {
160 MaybeLock lock(need_to_lock_);
161 gpu_command_buffer_->SetParseError(error);
162 }
163 virtual void SetContextLostReason(
164 gpu::error::ContextLostReason reason) OVERRIDE {
165 MaybeLock lock(need_to_lock_);
166 gpu_command_buffer_->SetContextLostReason(reason);
167 }
168 virtual uint32 InsertSyncPoint() OVERRIDE {
169 MaybeLock lock(need_to_lock_);
170 return gpu_command_buffer_->InsertSyncPoint();
171 }
172
173 // Weak pointer - see class Graphics3D for the scopted_ptr.
174 gpu::CommandBuffer* gpu_command_buffer_;
175
176 bool need_to_lock_;
177 };
178
179 Graphics3D::Graphics3D(const HostResource& resource) 55 Graphics3D::Graphics3D(const HostResource& resource)
180 : PPB_Graphics3D_Shared(resource), 56 : PPB_Graphics3D_Shared(resource) {
181 num_already_locked_calls_(0) {
182 } 57 }
183 58
184 Graphics3D::~Graphics3D() { 59 Graphics3D::~Graphics3D() {
185 if (gles2_impl()) 60 if (gles2_impl())
186 DestroyGLES2Impl(); 61 DestroyGLES2Impl();
187 } 62 }
188 63
189 bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2) { 64 bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2) {
190 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this); 65 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
191 if (!dispatcher) 66 if (!dispatcher)
192 return false; 67 return false;
193 68
194 command_buffer_.reset( 69 command_buffer_.reset(
195 new PpapiCommandBufferProxy(host_resource(), dispatcher)); 70 new PpapiCommandBufferProxy(host_resource(), dispatcher));
196 locking_command_buffer_.reset(
197 new LockingCommandBuffer(command_buffer_.get()));
198 71
199 ScopedNoLocking already_locked(this);
200 return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize, 72 return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize,
201 share_gles2); 73 share_gles2);
202 } 74 }
203 75
204 PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) { 76 PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
205 return PP_FALSE; 77 return PP_FALSE;
206 } 78 }
207 79
208 gpu::CommandBuffer::State Graphics3D::GetState() { 80 gpu::CommandBuffer::State Graphics3D::GetState() {
209 return GetErrorState(); 81 return GetErrorState();
(...skipping 25 matching lines...) Expand all
235 int32_t last_known_get) { 107 int32_t last_known_get) {
236 return GetErrorState(); 108 return GetErrorState();
237 } 109 }
238 110
239 uint32_t Graphics3D::InsertSyncPoint() { 111 uint32_t Graphics3D::InsertSyncPoint() {
240 NOTREACHED(); 112 NOTREACHED();
241 return 0; 113 return 0;
242 } 114 }
243 115
244 gpu::CommandBuffer* Graphics3D::GetCommandBuffer() { 116 gpu::CommandBuffer* Graphics3D::GetCommandBuffer() {
245 return locking_command_buffer_.get(); 117 return command_buffer_.get();
246 } 118 }
247 119
248 gpu::GpuControl* Graphics3D::GetGpuControl() { 120 gpu::GpuControl* Graphics3D::GetGpuControl() {
249 return command_buffer_.get(); 121 return command_buffer_.get();
250 } 122 }
251 123
252 int32 Graphics3D::DoSwapBuffers() { 124 int32 Graphics3D::DoSwapBuffers() {
253 // gles2_impl()->SwapBuffers() results in CommandBuffer calls, and we already
254 // have the proxy lock.
255 ScopedNoLocking already_locked(this);
256
257 gles2_impl()->SwapBuffers(); 125 gles2_impl()->SwapBuffers();
258 IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers( 126 IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
259 API_ID_PPB_GRAPHICS_3D, host_resource()); 127 API_ID_PPB_GRAPHICS_3D, host_resource());
260 msg->set_unblock(true); 128 msg->set_unblock(true);
261 PluginDispatcher::GetForResource(this)->Send(msg); 129 PluginDispatcher::GetForResource(this)->Send(msg);
262 130
263 return PP_OK_COMPLETIONPENDING; 131 return PP_OK_COMPLETIONPENDING;
264 } 132 }
265 133
266 void Graphics3D::PushAlreadyLocked() {
267 ppapi::ProxyLock::AssertAcquired();
268 if (!locking_command_buffer_) {
269 NOTREACHED();
270 return;
271 }
272 if (num_already_locked_calls_ == 0)
273 locking_command_buffer_->set_need_to_lock(false);
274 ++num_already_locked_calls_;
275 }
276
277 void Graphics3D::PopAlreadyLocked() {
278 // We must have Pushed before we can Pop.
279 DCHECK(!locking_command_buffer_->need_to_lock());
280 DCHECK_GT(num_already_locked_calls_, 0);
281 ppapi::ProxyLock::AssertAcquired();
282 if (!locking_command_buffer_) {
283 NOTREACHED();
284 return;
285 }
286 --num_already_locked_calls_;
287 if (num_already_locked_calls_ == 0)
288 locking_command_buffer_->set_need_to_lock(true);
289 }
290
291 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher) 134 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher)
292 : InterfaceProxy(dispatcher), 135 : InterfaceProxy(dispatcher),
293 callback_factory_(this) { 136 callback_factory_(this) {
294 } 137 }
295 138
296 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() { 139 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
297 } 140 }
298 141
299 // static 142 // static
300 PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource( 143 PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource(
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 int32_t result, 346 int32_t result,
504 const HostResource& context) { 347 const HostResource& context) {
505 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK( 348 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
506 API_ID_PPB_GRAPHICS_3D, context, result)); 349 API_ID_PPB_GRAPHICS_3D, context, result));
507 } 350 }
508 #endif // !defined(OS_NACL) 351 #endif // !defined(OS_NACL)
509 352
510 } // namespace proxy 353 } // namespace proxy
511 } // namespace ppapi 354 } // namespace ppapi
512 355
OLDNEW
« no previous file with comments | « ppapi/proxy/ppb_graphics_3d_proxy.h ('k') | ppapi/shared_impl/ppb_graphics_3d_shared.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698