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

Side by Side Diff: content/gpu/gpu_command_buffer_stub.cc

Issue 6793054: Moved code that runs in both the browser and GPU process from content/gpu to content/common/gpu. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 8 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 | « content/gpu/gpu_command_buffer_stub.h ('k') | content/gpu/gpu_config.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 #if defined(ENABLE_GPU)
6
7 #include "base/process_util.h"
8 #include "base/shared_memory.h"
9 #include "build/build_config.h"
10 #include "content/common/gpu_messages.h"
11 #include "content/common/child_thread.h"
12 #include "content/gpu/gpu_channel.h"
13 #include "content/gpu/gpu_command_buffer_stub.h"
14 #include "content/gpu/gpu_render_thread.h"
15 #include "content/gpu/gpu_watchdog_thread.h"
16 #include "gpu/common/gpu_trace_event.h"
17
18 #if defined(OS_WIN)
19 #include "base/win/wrapped_window_proc.h"
20 #endif
21
22 using gpu::Buffer;
23
24 #if defined(OS_WIN)
25 #define kCompositorWindowOwner L"CompositorWindowOwner"
26 #endif // defined(OS_WIN)
27
28 GpuCommandBufferStub::GpuCommandBufferStub(
29 GpuChannel* channel,
30 gfx::PluginWindowHandle handle,
31 GpuCommandBufferStub* parent,
32 const gfx::Size& size,
33 const gpu::gles2::DisallowedExtensions& disallowed_extensions,
34 const std::string& allowed_extensions,
35 const std::vector<int32>& attribs,
36 uint32 parent_texture_id,
37 int32 route_id,
38 int32 renderer_id,
39 int32 render_view_id,
40 GpuWatchdogThread* gpu_watchdog_thread)
41 : channel_(channel),
42 handle_(handle),
43 parent_(
44 parent ? parent->AsWeakPtr() : base::WeakPtr<GpuCommandBufferStub>()),
45 initial_size_(size),
46 disallowed_extensions_(disallowed_extensions),
47 allowed_extensions_(allowed_extensions),
48 requested_attribs_(attribs),
49 parent_texture_id_(parent_texture_id),
50 route_id_(route_id),
51 #if defined(OS_WIN)
52 compositor_window_(NULL),
53 #endif // defined(OS_WIN)
54 renderer_id_(renderer_id),
55 render_view_id_(render_view_id),
56 watchdog_thread_(gpu_watchdog_thread) {
57 }
58
59 #if defined(OS_WIN)
60 static LRESULT CALLBACK CompositorWindowProc(
61 HWND hwnd,
62 UINT message,
63 WPARAM wparam,
64 LPARAM lparam) {
65 switch (message) {
66 case WM_ERASEBKGND:
67 return 0;
68 case WM_DESTROY:
69 RemoveProp(hwnd, kCompositorWindowOwner);
70 return 0;
71 case WM_PAINT: {
72 PAINTSTRUCT paint;
73 HDC dc = BeginPaint(hwnd, &paint);
74 if (dc) {
75 HANDLE h = GetProp(hwnd, kCompositorWindowOwner);
76 if (h) {
77 GpuCommandBufferStub* stub =
78 reinterpret_cast<GpuCommandBufferStub*>(h);
79 stub->OnCompositorWindowPainted();
80 }
81 EndPaint(hwnd, &paint);
82 }
83 break;
84 }
85 default:
86 return DefWindowProc(hwnd, message, wparam, lparam);
87 }
88 return 0;
89 }
90
91 bool GpuCommandBufferStub::CreateCompositorWindow() {
92 DCHECK(handle_ != gfx::kNullPluginWindow);
93 HWND host_window = static_cast<HWND>(handle_);
94
95 // Create the compositor window itself.
96 DCHECK(host_window);
97 static ATOM window_class = 0;
98 if (!window_class) {
99 WNDCLASSEX wcex;
100 wcex.cbSize = sizeof(wcex);
101 wcex.style = 0;
102 wcex.lpfnWndProc = base::win::WrappedWindowProc<CompositorWindowProc>;
103 wcex.cbClsExtra = 0;
104 wcex.cbWndExtra = 0;
105 wcex.hInstance = GetModuleHandle(NULL);
106 wcex.hIcon = 0;
107 wcex.hCursor = 0;
108 wcex.hbrBackground = NULL;
109 wcex.lpszMenuName = 0;
110 wcex.lpszClassName = L"CompositorWindowClass";
111 wcex.hIconSm = 0;
112 window_class = RegisterClassEx(&wcex);
113 DCHECK(window_class);
114 }
115
116 HWND compositor_window = CreateWindowEx(
117 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
118 MAKEINTATOM(window_class),
119 0,
120 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED,
121 0, 0,
122 0, 0,
123 host_window,
124 0,
125 GetModuleHandle(NULL),
126 0);
127 if (!compositor_window) {
128 compositor_window_ = gfx::kNullPluginWindow;
129 return false;
130 }
131 SetProp(compositor_window, kCompositorWindowOwner,
132 reinterpret_cast<HANDLE>(this));
133
134 RECT parent_rect;
135 GetClientRect(host_window, &parent_rect);
136
137 UINT flags = SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER |
138 SWP_NOACTIVATE | SWP_DEFERERASE | SWP_SHOWWINDOW;
139 SetWindowPos(compositor_window,
140 NULL,
141 0, 0,
142 parent_rect.right - parent_rect.left,
143 parent_rect.bottom - parent_rect.top,
144 flags);
145 compositor_window_ = static_cast<gfx::PluginWindowHandle>(compositor_window);
146 return true;
147 }
148
149 void GpuCommandBufferStub::OnCompositorWindowPainted() {
150 GpuRenderThread* render_thread = channel_->gpu_render_thread();
151 render_thread->Send(new GpuHostMsg_ScheduleComposite(
152 renderer_id_, render_view_id_));
153 }
154 #endif // defined(OS_WIN)
155
156
157 GpuCommandBufferStub::~GpuCommandBufferStub() {
158 if (processor_.get()) {
159 processor_->Destroy();
160 }
161 #if defined(OS_WIN)
162 if (compositor_window_) {
163 DestroyWindow(static_cast<HWND>(compositor_window_));
164 compositor_window_ = NULL;
165 }
166 #endif // defined(OS_WIN)
167
168 GpuRenderThread* render_thread = channel_->gpu_render_thread();
169 render_thread->Send(new GpuHostMsg_DestroyCommandBuffer(
170 handle_, renderer_id_, render_view_id_));
171 }
172
173 bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
174 bool handled = true;
175 IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message)
176 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Initialize, OnInitialize);
177 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetState, OnGetState);
178 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncGetState, OnAsyncGetState);
179 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Flush, OnFlush);
180 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush);
181 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateTransferBuffer,
182 OnCreateTransferBuffer);
183 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterTransferBuffer,
184 OnRegisterTransferBuffer);
185 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyTransferBuffer,
186 OnDestroyTransferBuffer);
187 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetTransferBuffer,
188 OnGetTransferBuffer);
189 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ResizeOffscreenFrameBuffer,
190 OnResizeOffscreenFrameBuffer);
191 #if defined(OS_MACOSX)
192 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetWindowSize, OnSetWindowSize);
193 #endif // defined(OS_MACOSX)
194 IPC_MESSAGE_UNHANDLED(handled = false)
195 IPC_END_MESSAGE_MAP()
196 DCHECK(handled);
197 return handled;
198 }
199
200 bool GpuCommandBufferStub::Send(IPC::Message* message) {
201 return channel_->Send(message);
202 }
203
204 void GpuCommandBufferStub::OnInitialize(
205 base::SharedMemoryHandle ring_buffer,
206 int32 size,
207 bool* result) {
208 DCHECK(!command_buffer_.get());
209
210 *result = false;
211
212 command_buffer_.reset(new gpu::CommandBufferService);
213
214 // Create the child window, if needed
215 #if defined(OS_WIN)
216 gfx::PluginWindowHandle output_window_handle;
217 if (handle_) {
218 if (!CreateCompositorWindow()) {
219 return;
220 }
221 output_window_handle = compositor_window_;
222 } else {
223 output_window_handle = handle_;
224 }
225 #else
226 gfx::PluginWindowHandle output_window_handle = handle_;
227 #endif // defined(OS_WIN)
228
229 #if defined(OS_WIN)
230 // Windows dups the shared memory handle it receives into the current process
231 // and closes it when this variable goes out of scope.
232 base::SharedMemory shared_memory(ring_buffer,
233 false,
234 channel_->renderer_process());
235 #else
236 // POSIX receives a dup of the shared memory handle and closes the dup when
237 // this variable goes out of scope.
238 base::SharedMemory shared_memory(ring_buffer, false);
239 #endif
240
241 // Initialize the CommandBufferService and GPUProcessor.
242 if (command_buffer_->Initialize(&shared_memory, size)) {
243 gpu::GPUProcessor* parent_processor =
244 parent_ ? parent_->processor_.get() : NULL;
245 processor_.reset(new gpu::GPUProcessor(command_buffer_.get(), NULL));
246 if (processor_->Initialize(
247 output_window_handle,
248 initial_size_,
249 disallowed_extensions_,
250 allowed_extensions_.c_str(),
251 requested_attribs_,
252 parent_processor,
253 parent_texture_id_)) {
254 command_buffer_->SetPutOffsetChangeCallback(
255 NewCallback(processor_.get(),
256 &gpu::GPUProcessor::ProcessCommands));
257 processor_->SetSwapBuffersCallback(
258 NewCallback(this, &GpuCommandBufferStub::OnSwapBuffers));
259 if (watchdog_thread_)
260 processor_->SetCommandProcessedCallback(
261 NewCallback(this, &GpuCommandBufferStub::OnCommandProcessed));
262
263 #if defined(OS_MACOSX)
264 if (handle_) {
265 // This context conceptually puts its output directly on the
266 // screen, rendered by the accelerated plugin layer in
267 // RenderWidgetHostViewMac. Set up a pathway to notify the
268 // browser process when its contents change.
269 processor_->SetSwapBuffersCallback(
270 NewCallback(this,
271 &GpuCommandBufferStub::SwapBuffersCallback));
272 }
273 #endif // defined(OS_MACOSX)
274
275 // Set up a pathway for resizing the output window or framebuffer at the
276 // right time relative to other GL commands.
277 processor_->SetResizeCallback(
278 NewCallback(this, &GpuCommandBufferStub::ResizeCallback));
279
280 *result = true;
281 } else {
282 processor_.reset();
283 command_buffer_.reset();
284 }
285 }
286 }
287
288 void GpuCommandBufferStub::OnCommandProcessed() {
289 if (watchdog_thread_)
290 watchdog_thread_->CheckArmed();
291 }
292
293 void GpuCommandBufferStub::OnGetState(gpu::CommandBuffer::State* state) {
294 *state = command_buffer_->GetState();
295 }
296
297 void GpuCommandBufferStub::OnAsyncGetState() {
298 gpu::CommandBuffer::State state = command_buffer_->GetState();
299 Send(new GpuCommandBufferMsg_UpdateState(route_id_, state));
300 }
301
302 void GpuCommandBufferStub::OnFlush(int32 put_offset,
303 gpu::CommandBuffer::State* state) {
304 *state = command_buffer_->FlushSync(put_offset);
305 }
306
307 void GpuCommandBufferStub::OnAsyncFlush(int32 put_offset) {
308 gpu::CommandBuffer::State state = command_buffer_->FlushSync(put_offset);
309 Send(new GpuCommandBufferMsg_UpdateState(route_id_, state));
310 }
311
312 void GpuCommandBufferStub::OnCreateTransferBuffer(int32 size, int32* id) {
313 *id = command_buffer_->CreateTransferBuffer(size);
314 }
315
316 void GpuCommandBufferStub::OnRegisterTransferBuffer(
317 base::SharedMemoryHandle transfer_buffer,
318 size_t size,
319 int32* id) {
320 #if defined(OS_WIN)
321 // Windows dups the shared memory handle it receives into the current process
322 // and closes it when this variable goes out of scope.
323 base::SharedMemory shared_memory(transfer_buffer,
324 false,
325 channel_->renderer_process());
326 #else
327 // POSIX receives a dup of the shared memory handle and closes the dup when
328 // this variable goes out of scope.
329 base::SharedMemory shared_memory(transfer_buffer, false);
330 #endif
331
332 *id = command_buffer_->RegisterTransferBuffer(&shared_memory, size);
333 }
334
335 void GpuCommandBufferStub::OnDestroyTransferBuffer(int32 id) {
336 command_buffer_->DestroyTransferBuffer(id);
337 }
338
339 void GpuCommandBufferStub::OnGetTransferBuffer(
340 int32 id,
341 base::SharedMemoryHandle* transfer_buffer,
342 uint32* size) {
343 *transfer_buffer = base::SharedMemoryHandle();
344 *size = 0;
345
346 // Fail if the renderer process has not provided its process handle.
347 if (!channel_->renderer_process())
348 return;
349
350 Buffer buffer = command_buffer_->GetTransferBuffer(id);
351 if (buffer.shared_memory) {
352 // Assume service is responsible for duplicating the handle to the calling
353 // process.
354 buffer.shared_memory->ShareToProcess(channel_->renderer_process(),
355 transfer_buffer);
356 *size = buffer.size;
357 }
358 }
359
360 void GpuCommandBufferStub::OnResizeOffscreenFrameBuffer(const gfx::Size& size) {
361 processor_->ResizeOffscreenFrameBuffer(size);
362 }
363
364 void GpuCommandBufferStub::OnSwapBuffers() {
365 GPU_TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSwapBuffers");
366 Send(new GpuCommandBufferMsg_SwapBuffers(route_id_));
367 }
368
369 #if defined(OS_MACOSX)
370 void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) {
371 GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread();
372 // Try using the IOSurface version first.
373 uint64 new_backing_store = processor_->SetWindowSizeForIOSurface(size);
374 if (new_backing_store) {
375 GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params;
376 params.renderer_id = renderer_id_;
377 params.render_view_id = render_view_id_;
378 params.window = handle_;
379 params.width = size.width();
380 params.height = size.height();
381 params.identifier = new_backing_store;
382 gpu_render_thread->Send(
383 new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params));
384 } else {
385 // TODO(kbr): figure out what to do here. It wouldn't be difficult
386 // to support the compositor on 10.5, but the performance would be
387 // questionable.
388 NOTREACHED();
389 }
390 }
391
392 void GpuCommandBufferStub::SwapBuffersCallback() {
393 OnSwapBuffers();
394 GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread();
395 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
396 params.renderer_id = renderer_id_;
397 params.render_view_id = render_view_id_;
398 params.window = handle_;
399 params.surface_id = processor_->GetSurfaceId();
400 params.route_id = route_id();
401 params.swap_buffers_count = processor_->swap_buffers_count();
402 gpu_render_thread->Send(
403 new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
404 }
405
406 void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped(
407 uint64 swap_buffers_count) {
408 processor_->set_acknowledged_swap_buffers_count(swap_buffers_count);
409 // Wake up the GpuProcessor to start doing work again.
410 processor_->ScheduleProcessCommands();
411 }
412 #endif // defined(OS_MACOSX)
413
414 void GpuCommandBufferStub::ResizeCallback(gfx::Size size) {
415 if (handle_ == gfx::kNullPluginWindow) {
416 processor_->decoder()->ResizeOffscreenFrameBuffer(size);
417 processor_->decoder()->UpdateOffscreenFrameBufferSize();
418 } else {
419 #if defined(OS_LINUX) && !defined(TOUCH_UI)
420 GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread();
421 bool result = false;
422 gpu_render_thread->Send(
423 new GpuHostMsg_ResizeXID(handle_, size, &result));
424 #elif defined(OS_WIN)
425 HWND hwnd = static_cast<HWND>(compositor_window_);
426 UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS |
427 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE;
428 SetWindowPos(hwnd, NULL, 0, 0, size.width(), size.height(), swp_flags);
429 #endif // defined(OS_LINUX)
430 }
431 }
432
433 #endif // defined(ENABLE_GPU)
OLDNEW
« no previous file with comments | « content/gpu/gpu_command_buffer_stub.h ('k') | content/gpu/gpu_config.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698