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

Side by Side Diff: content/common/gpu/image_transport_surface_linux.cc

Issue 7395020: Create new GLSurface for cross process image transport. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: "" Created 9 years, 5 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/common/gpu/image_transport_surface_linux.h ('k') | content/content_common.gypi » ('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 "content/common/gpu/image_transport_surface_linux.h"
8
9 // This conflicts with the defines in Xlib.h and must come first.
10 #include "content/common/gpu/gpu_messages.h"
11
12 #include <map>
13 #include <X11/Xlib.h>
14 #include <X11/extensions/Xcomposite.h>
15
16 #include "base/callback.h"
17 #include "content/common/gpu/gpu_channel.h"
18 #include "content/common/gpu/gpu_channel_manager.h"
19 #include "content/common/gpu/gpu_command_buffer_stub.h"
20 #include "gpu/command_buffer/service/gpu_scheduler.h"
21 #include "third_party/angle/include/EGL/egl.h"
22 #include "third_party/angle/include/EGL/eglext.h"
23 #include "ui/gfx/gl/gl_bindings.h"
24 #include "ui/gfx/gl/gl_implementation.h"
25 #include "ui/gfx/gl/gl_surface_egl.h"
26 #include "ui/gfx/gl/gl_surface_glx.h"
27 #include "ui/gfx/surface/accelerated_surface_linux.h"
28
29 namespace {
30
31 // We are backed by an Pbuffer offscreen surface for the purposes of creating a
32 // context, but use FBOs to render to X Pixmap backed EGLImages.
33 class EGLImageTransportSurface : public ImageTransportSurface,
34 public gfx::PbufferGLSurfaceEGL {
35 public:
36 explicit EGLImageTransportSurface(GpuCommandBufferStub* stub);
37
38 // GLSurface implementation
39 virtual bool Initialize() OVERRIDE;
40 virtual void Destroy() OVERRIDE;
41 virtual bool IsOffscreen() OVERRIDE;
42 virtual bool SwapBuffers() OVERRIDE;
43 virtual gfx::Size GetSize() OVERRIDE;
44 virtual void OnMakeCurrent() OVERRIDE;
45 virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
46
47 protected:
48 // ImageTransportSurface implementation
49 virtual void OnSetSurfaceACK(uint64 surface_id) OVERRIDE;
50 virtual void OnBuffersSwappedACK() OVERRIDE;
51 virtual void Resize(gfx::Size size) OVERRIDE;
52
53 private:
54 virtual ~EGLImageTransportSurface() OVERRIDE;
55 void ReleaseSurface(scoped_refptr<AcceleratedSurface>& surface);
56
57 uint32 fbo_id_;
58 uint32 depth_id_;
59 gfx::Size depth_buffer_size_;
60
61 scoped_refptr<AcceleratedSurface> back_surface_;
62 scoped_refptr<AcceleratedSurface> front_surface_;
63
64 DISALLOW_COPY_AND_ASSIGN(EGLImageTransportSurface);
65 };
66
67 // We are backed by an Pbuffer offscreen surface for the purposes of creating a
68 // context, but use FBOs to render to X Pixmap backed EGLImages.
69 class GLXImageTransportSurface : public ImageTransportSurface,
70 public gfx::NativeViewGLSurfaceGLX {
71 public:
72 explicit GLXImageTransportSurface(GpuCommandBufferStub* stub);
73
74 // gfx::GLSurface implementation:
75 virtual bool Initialize() OVERRIDE;
76 virtual void Destroy() OVERRIDE;
77 virtual bool SwapBuffers() OVERRIDE;
78 virtual gfx::Size GetSize() OVERRIDE;
79
80 protected:
81 // ImageTransportSurface implementation:
82 void OnSetSurfaceACK(uint64 surface_id) OVERRIDE;
83 void OnBuffersSwappedACK() OVERRIDE;
84 void Resize(gfx::Size size) OVERRIDE;
85
86 private:
87 virtual ~GLXImageTransportSurface();
88
89 // Tell the browser to release the surface.
90 void ReleaseSurface();
91
92 XID dummy_parent_;
93 gfx::Size size_;
94
95 // Whether or not the image has been bound on the browser side.
96 bool bound_;
97
98 DISALLOW_COPY_AND_ASSIGN(GLXImageTransportSurface);
99 };
100
101 EGLImageTransportSurface::EGLImageTransportSurface(GpuCommandBufferStub* stub) :
102 ImageTransportSurface(stub),
103 gfx::PbufferGLSurfaceEGL(false, gfx::Size(1,1)),
104 fbo_id_(0) {
105 }
106
107 EGLImageTransportSurface::~EGLImageTransportSurface() {
108 }
109
110 bool EGLImageTransportSurface::Initialize() {
111 if (!ImageTransportSurface::Initialize())
112 return false;
113 return PbufferGLSurfaceEGL::Initialize();
114 }
115
116 void EGLImageTransportSurface::Destroy() {
117 if (depth_id_) {
118 glDeleteRenderbuffersEXT(1, &depth_id_);
119 depth_id_ = 0;
120 }
121
122 if (back_surface_.get())
123 ReleaseSurface(back_surface_);
124 if (front_surface_.get())
125 ReleaseSurface(front_surface_);
126
127 ImageTransportSurface::Destroy();
128 PbufferGLSurfaceEGL::Destroy();
129 }
130
131 bool EGLImageTransportSurface::IsOffscreen() {
132 return false;
133 }
134
135 void EGLImageTransportSurface::OnMakeCurrent() {
136 if (fbo_id_)
137 return;
138
139 glGenFramebuffersEXT(1, &fbo_id_);
140 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_);
141 Resize(gfx::Size(1,1));
142
143 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
144 if (status != GL_FRAMEBUFFER_COMPLETE) {
145 LOG(ERROR) << "Framebuffer incomplete.";
146 }
147 }
148
149 unsigned int EGLImageTransportSurface::GetBackingFrameBufferObject() {
150 return fbo_id_;
151 }
152
153 void EGLImageTransportSurface::ReleaseSurface(
154 scoped_refptr<AcceleratedSurface>& surface) {
155 if (surface.get()) {
156 GpuHostMsg_AcceleratedSurfaceRelease_Params params;
157 params.renderer_id = stub()->renderer_id();
158 params.render_view_id = stub()->render_view_id();
159 params.identifier = back_surface_->pixmap();
160 params.route_id = route_id();
161 Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
162 surface = NULL;
163 }
164 }
165
166 void EGLImageTransportSurface::Resize(gfx::Size size) {
167 if (back_surface_.get())
168 ReleaseSurface(back_surface_);
169
170 if (depth_id_ && depth_buffer_size_ != size) {
171 glDeleteRenderbuffersEXT(1, &depth_id_);
172 depth_id_ = 0;
173 }
174
175 if (!depth_id_) {
176 glGenRenderbuffersEXT(1, &depth_id_);
177 glBindRenderbufferEXT(GL_RENDERBUFFER, depth_id_);
178 glRenderbufferStorageEXT(GL_RENDERBUFFER,
179 GL_DEPTH24_STENCIL8,
180 size.width(),
181 size.height());
182 glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
183 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
184 GL_DEPTH_ATTACHMENT,
185 GL_RENDERBUFFER,
186 depth_id_);
187 depth_buffer_size_ = size;
188 }
189
190 back_surface_ = new AcceleratedSurface(size);
191 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
192 GL_COLOR_ATTACHMENT0,
193 GL_TEXTURE_2D,
194 back_surface_->texture(),
195 0);
196 glFlush();
197
198 GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params;
199 params.renderer_id = stub()->renderer_id();
200 params.render_view_id = stub()->render_view_id();
201 params.width = size.width();
202 params.height = size.height();
203 params.identifier = back_surface_->pixmap();
204 params.route_id = route_id();
205 Send(new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params));
206
207 scheduler()->SetScheduled(false);
208 }
209
210 bool EGLImageTransportSurface::SwapBuffers() {
211 front_surface_.swap(back_surface_);
212 DCHECK_NE(front_surface_.get(), static_cast<AcceleratedSurface*>(NULL));
213 glFlush();
214
215 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
216 params.renderer_id = stub()->renderer_id();
217 params.render_view_id = stub()->render_view_id();
218 params.surface_id = front_surface_->pixmap();
219 params.route_id = route_id();
220 Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
221
222 gfx::Size expected_size = front_surface_->size();
223 if (!back_surface_.get() || back_surface_->size() != expected_size) {
224 Resize(expected_size);
225 } else {
226 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
227 GL_COLOR_ATTACHMENT0,
228 GL_TEXTURE_2D,
229 back_surface_->texture(),
230 0);
231 }
232 scheduler()->SetScheduled(false);
233 return true;
234 }
235
236 gfx::Size EGLImageTransportSurface::GetSize() {
237 return back_surface_->size();
238 }
239
240 void EGLImageTransportSurface::OnSetSurfaceACK(
241 uint64 surface_id) {
242 DCHECK_EQ(back_surface_->pixmap(), surface_id);
243 scheduler()->SetScheduled(true);
244 }
245
246 void EGLImageTransportSurface::OnBuffersSwappedACK() {
247 scheduler()->SetScheduled(true);
248 }
249
250 GLXImageTransportSurface::GLXImageTransportSurface(GpuCommandBufferStub* stub) :
251 ImageTransportSurface(stub),
252 gfx::NativeViewGLSurfaceGLX(),
253 dummy_parent_(0),
254 size_(1, 1),
255 bound_(false) {
256 }
257
258 GLXImageTransportSurface::~GLXImageTransportSurface() {
259 }
260
261 bool GLXImageTransportSurface::Initialize() {
262 // Create a dummy window to host the real window.
263 Display* dpy = gfx::GLSurfaceGLX::GetDisplay();
264 XSetWindowAttributes swa;
265 swa.event_mask = StructureNotifyMask;
266 swa.override_redirect = True;
267 dummy_parent_ = XCreateWindow(
268 dpy,
269 RootWindow(dpy, DefaultScreen(dpy)), // parent
270 -100, -100, 1, 1,
271 0, // border width
272 CopyFromParent, // depth
273 InputOutput,
274 CopyFromParent, // visual
275 CWEventMask | CWOverrideRedirect, &swa);
276 XMapWindow(dpy, dummy_parent_);
277
278 swa.event_mask = StructureNotifyMask;
279 swa.override_redirect = false;
280 window_ = XCreateWindow(dpy,
281 dummy_parent_,
282 0, 0, size_.width(), size_.height(),
283 0, // border width
284 CopyFromParent, // depth
285 InputOutput,
286 CopyFromParent, // visual
287 CWEventMask, &swa);
288 XMapWindow(dpy, window_);
289 while(1) {
290 XEvent event;
291 XNextEvent(dpy, &event);
292 if (event.type == MapNotify && event.xmap.window == window_)
293 break;
294 }
295 // Manual setting must be used to avoid unnecessary rendering by server.
296 XCompositeRedirectWindow(dpy, window_, CompositeRedirectManual);
297 Resize(size_);
298
299 if (!ImageTransportSurface::Initialize())
300 return false;
301 return gfx::NativeViewGLSurfaceGLX::Initialize();
302 }
303
304 void GLXImageTransportSurface::Destroy() {
305 if (bound_)
306 ReleaseSurface();
307
308 if (window_) {
309 Display* dpy = gfx::GLSurfaceGLX::GetDisplay();
310 XDestroyWindow(dpy, window_);
311 XDestroyWindow(dpy, dummy_parent_);
312 }
313
314 ImageTransportSurface::Destroy();
315 gfx::NativeViewGLSurfaceGLX::Destroy();
316 }
317
318 void GLXImageTransportSurface::ReleaseSurface() {
319 DCHECK(bound_);
320 GpuHostMsg_AcceleratedSurfaceRelease_Params params;
321 params.renderer_id = stub()->renderer_id();
322 params.render_view_id = stub()->render_view_id();
323 params.identifier = window_;
324 params.route_id = route_id();
325 Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
326 }
327
328 void GLXImageTransportSurface::Resize(gfx::Size size) {
329 size_ = size;
330 if (bound_) {
331 ReleaseSurface();
332 bound_ = false;
333 }
334
335 Display* dpy = gfx::GLSurfaceGLX::GetDisplay();
336 XResizeWindow(dpy, window_, size_.width(), size_.height());
337 XFlush(dpy);
338
339 GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params;
340 params.renderer_id = stub()->renderer_id();
341 params.render_view_id = stub()->render_view_id();
342 params.width = size_.width();
343 params.height = size_.height();
344 params.identifier = window_;
345 params.route_id = route_id();
346 Send(new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params));
347
348 scheduler()->SetScheduled(false);
349 }
350
351 bool GLXImageTransportSurface::SwapBuffers() {
352 gfx::NativeViewGLSurfaceGLX::SwapBuffers();
353 glFlush();
354
355 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
356 params.renderer_id = stub()->renderer_id();
357 params.render_view_id = stub()->render_view_id();
358 params.surface_id = window_;
359 params.route_id = route_id();
360 Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
361
362 return true;
363 }
364
365 gfx::Size GLXImageTransportSurface::GetSize() {
366 return size_;
367 }
368
369 void GLXImageTransportSurface::OnSetSurfaceACK(
370 uint64 surface_id) {
371 DCHECK(!bound_);
372 bound_ = true;
373 scheduler()->SetScheduled(true);
374 }
375
376 void GLXImageTransportSurface::OnBuffersSwappedACK() {
377 }
378
379 } // namespace
380
381 ImageTransportSurface::ImageTransportSurface(GpuCommandBufferStub* stub) :
382 stub_(stub) {
383 GpuChannelManager* gpu_channel_manager
384 = stub_->channel()->gpu_channel_manager();
385 route_id_ = gpu_channel_manager->GenerateRouteID();
386 gpu_channel_manager->AddRoute(route_id_, this);
387 }
388
389 ImageTransportSurface::~ImageTransportSurface() {
390 GpuChannelManager* gpu_channel_manager
391 = stub_->channel()->gpu_channel_manager();
392 gpu_channel_manager->RemoveRoute(route_id_);
393 }
394
395 bool ImageTransportSurface::Initialize() {
396 scheduler()->SetResizeCallback(
397 NewCallback(this, &ImageTransportSurface::Resize));
398 return true;
399 }
400
401 void ImageTransportSurface::Destroy() {
402 scheduler()->SetResizeCallback(NULL);
403 }
404
405 bool ImageTransportSurface::OnMessageReceived(const IPC::Message& message) {
406 bool handled = true;
407 IPC_BEGIN_MESSAGE_MAP(ImageTransportSurface, message)
408 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_SetSurfaceACK,
409 OnSetSurfaceACK)
410 IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BuffersSwappedACK,
411 OnBuffersSwappedACK)
412 IPC_MESSAGE_UNHANDLED(handled = false)
413 IPC_END_MESSAGE_MAP()
414 return handled;
415 }
416
417 bool ImageTransportSurface::Send(IPC::Message* message) {
418 GpuChannelManager* gpu_channel_manager =
419 stub_->channel()->gpu_channel_manager();
420 return gpu_channel_manager->Send(message);
421 }
422
423 gpu::GpuScheduler* ImageTransportSurface::scheduler() {
424 return stub_->scheduler();
425 }
426
427 // static
428 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
429 GpuCommandBufferStub* stub) {
430 scoped_refptr<gfx::GLSurface> surface;
431 switch (gfx::GetGLImplementation()) {
432 case gfx::kGLImplementationDesktopGL:
433 surface = new GLXImageTransportSurface(stub);
434 break;
435 case gfx::kGLImplementationEGLGLES2:
436 surface = new EGLImageTransportSurface(stub);
437 break;
438 default:
439 NOTREACHED();
440 return NULL;
441 }
442 if (surface->Initialize())
443 return surface;
444 else
445 return NULL;
446 }
447
448 #endif // defined(USE_GPU)
OLDNEW
« no previous file with comments | « content/common/gpu/image_transport_surface_linux.h ('k') | content/content_common.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698