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

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

Issue 10696221: Aura: Less image transport IPCs and less code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 8 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
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 "content/common/gpu/image_transport_surface.h" 5 #include "content/common/gpu/image_transport_surface.h"
6 6
7 // This conflicts with the defines in Xlib.h and must come first.
8 #include "content/common/gpu/gpu_messages.h"
9
10 #include <X11/Xlib.h>
11 #include <X11/extensions/Xcomposite.h>
12 #include <map>
13 #include <vector>
14
15 // Note: these must be included before anything that includes gl_bindings.h
16 // They're effectively standard library headers.
17 #include "third_party/khronos/EGL/egl.h"
18 #include "third_party/khronos/EGL/eglext.h"
19 #include "third_party/mesa/MesaLib/include/GL/osmesa.h"
20
21 #include "base/bind.h"
22 #include "base/debug/trace_event.h"
23 #include "base/memory/weak_ptr.h"
24 #include "content/common/gpu/gpu_channel.h"
25 #include "content/common/gpu/gpu_channel_manager.h"
26 #include "content/common/gpu/gpu_command_buffer_stub.h"
27 #include "content/common/gpu/texture_image_transport_surface.h" 7 #include "content/common/gpu/texture_image_transport_surface.h"
28 #include "gpu/command_buffer/service/gpu_scheduler.h"
29 #include "ui/gfx/rect.h"
30 #include "ui/gl/gl_bindings.h"
31 #include "ui/gl/gl_context.h"
32 #include "ui/gl/gl_implementation.h"
33 #include "ui/gl/gl_surface_egl.h"
34 #include "ui/gl/gl_surface_glx.h"
35 #include "ui/gl/gl_surface_osmesa.h"
36
37 namespace {
38
39 class ScopedDisplayLock {
40 public:
41 ScopedDisplayLock(Display* display): display_(display) {
42 XLockDisplay(display_);
43 }
44
45 ~ScopedDisplayLock() {
46 XUnlockDisplay(display_);
47 }
48
49 private:
50 Display* display_;
51
52 DISALLOW_COPY_AND_ASSIGN(ScopedDisplayLock);
53 };
54
55 // The GL context associated with the surface must be current when
56 // an instance is created or destroyed.
57 class EGLAcceleratedSurface : public base::RefCounted<EGLAcceleratedSurface> {
58 public:
59 explicit EGLAcceleratedSurface(const gfx::Size& size);
60 const gfx::Size& size() const { return size_; }
61 uint32 pixmap() const { return pixmap_; }
62 uint32 texture() const { return texture_; }
63
64 private:
65 ~EGLAcceleratedSurface();
66
67 gfx::Size size_;
68 void* image_;
69 uint32 pixmap_;
70 uint32 texture_;
71
72 friend class base::RefCounted<EGLAcceleratedSurface>;
73 DISALLOW_COPY_AND_ASSIGN(EGLAcceleratedSurface);
74 };
75
76 // We are backed by an Pbuffer offscreen surface for the purposes of creating a
77 // context, but use FBOs to render to X Pixmap backed EGLImages.
78 class EGLImageTransportSurface
79 : public ImageTransportSurface,
80 public gfx::PbufferGLSurfaceEGL,
81 public base::SupportsWeakPtr<EGLImageTransportSurface> {
82 public:
83 EGLImageTransportSurface(GpuChannelManager* manager,
84 GpuCommandBufferStub* stub);
85
86 // gfx::GLSurface implementation
87 virtual bool Initialize() OVERRIDE;
88 virtual void Destroy() OVERRIDE;
89 virtual bool IsOffscreen() OVERRIDE;
90 virtual bool SwapBuffers() OVERRIDE;
91 virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
92 virtual std::string GetExtensions() OVERRIDE;
93 virtual gfx::Size GetSize() OVERRIDE;
94 virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
95 virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
96 virtual void SetBackbufferAllocation(bool allocated) OVERRIDE;
97 virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
98
99 protected:
100 // ImageTransportSurface implementation
101 virtual void OnNewSurfaceACK(
102 uint64 surface_handle, TransportDIB::Handle shm_handle) OVERRIDE;
103 virtual void OnBufferPresented(uint32 sync_point) OVERRIDE;
104 virtual void OnResizeViewACK() OVERRIDE;
105 virtual void OnResize(gfx::Size size) OVERRIDE;
106
107 private:
108 virtual ~EGLImageTransportSurface() OVERRIDE;
109 void ReleaseSurface(scoped_refptr<EGLAcceleratedSurface>* surface);
110 void SendBuffersSwapped();
111 void SendPostSubBuffer(int x, int y, int width, int height);
112
113 // Tracks the current buffer allocation state.
114 bool backbuffer_suggested_allocation_;
115 bool frontbuffer_suggested_allocation_;
116
117 // The expected size when visible.
118 gfx::Size visible_size_;
119
120 uint32 fbo_id_;
121
122 scoped_refptr<EGLAcceleratedSurface> back_surface_;
123 scoped_refptr<EGLAcceleratedSurface> front_surface_;
124 gfx::Rect previous_damage_rect_;
125
126 // Whether or not we've successfully made the surface current once.
127 bool made_current_;
128
129 scoped_ptr<ImageTransportHelper> helper_;
130
131 DISALLOW_COPY_AND_ASSIGN(EGLImageTransportSurface);
132 };
133
134 // We render to an off-screen (but mapped) window that the browser process will
135 // read from via XComposite
136 class GLXImageTransportSurface
137 : public ImageTransportSurface,
138 public gfx::NativeViewGLSurfaceGLX,
139 public base::SupportsWeakPtr<GLXImageTransportSurface> {
140 public:
141 GLXImageTransportSurface(GpuChannelManager* manager,
142 GpuCommandBufferStub* stub);
143
144 // gfx::GLSurface implementation:
145 virtual bool Initialize() OVERRIDE;
146 virtual void Destroy() OVERRIDE;
147 virtual bool SwapBuffers() OVERRIDE;
148 virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
149 virtual std::string GetExtensions();
150 virtual gfx::Size GetSize() OVERRIDE;
151 virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
152 virtual void SetBackbufferAllocation(bool allocated) OVERRIDE;
153 virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
154
155 protected:
156 // ImageTransportSurface implementation:
157 virtual void OnNewSurfaceACK(
158 uint64 surface_handle, TransportDIB::Handle shm_handle) OVERRIDE;
159 virtual void OnBufferPresented(uint32 sync_point) OVERRIDE;
160 virtual void OnResizeViewACK() OVERRIDE;
161 virtual void OnResize(gfx::Size size) OVERRIDE;
162
163 private:
164 virtual ~GLXImageTransportSurface();
165
166 // Tell the browser to release the surface.
167 void ReleaseSurface();
168
169 void SendBuffersSwapped();
170 void SendPostSubBuffer(int x, int y, int width, int height);
171
172 void ResizeSurface(gfx::Size size);
173
174 // Tracks the current buffer allocation state.
175 bool backbuffer_suggested_allocation_;
176 bool frontbuffer_suggested_allocation_;
177
178 XID dummy_parent_;
179 gfx::Size size_;
180
181 // Whether or not the image has been bound on the browser side.
182 bool bound_;
183
184 // Whether or not we need to send a resize on the next swap.
185 bool needs_resize_;
186
187 // Whether or not we've successfully made the surface current once.
188 bool made_current_;
189
190 scoped_ptr<ImageTransportHelper> helper_;
191
192 DISALLOW_COPY_AND_ASSIGN(GLXImageTransportSurface);
193 };
194
195 // We render to a hunk of shared memory that we get from the browser.
196 // Swapping buffers simply means telling the browser to read the contents
197 // of the memory.
198 class OSMesaImageTransportSurface : public ImageTransportSurface,
199 public gfx::GLSurfaceOSMesa {
200 public:
201 OSMesaImageTransportSurface(GpuChannelManager* manager,
202 GpuCommandBufferStub* stub);
203
204 // gfx::GLSurface implementation:
205 virtual bool Initialize() OVERRIDE;
206 virtual void Destroy() OVERRIDE;
207 virtual bool IsOffscreen() OVERRIDE;
208 virtual bool SwapBuffers() OVERRIDE;
209 virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
210 virtual std::string GetExtensions() OVERRIDE;
211 virtual gfx::Size GetSize() OVERRIDE;
212
213 protected:
214 // ImageTransportSurface implementation:
215 virtual void OnNewSurfaceACK(
216 uint64 surface_handle, TransportDIB::Handle shm_handle) OVERRIDE;
217 virtual void OnBufferPresented(uint32 sync_point) OVERRIDE;
218 virtual void OnResizeViewACK() OVERRIDE;
219 virtual void OnResize(gfx::Size size) OVERRIDE;
220
221 private:
222 virtual ~OSMesaImageTransportSurface();
223
224 // Tell the browser to release the surface.
225 void ReleaseSurface();
226
227 scoped_ptr<TransportDIB> shared_mem_;
228 uint32 shared_id_;
229 gfx::Size size_;
230
231 scoped_ptr<ImageTransportHelper> helper_;
232
233 DISALLOW_COPY_AND_ASSIGN(OSMesaImageTransportSurface);
234 };
235
236 EGLAcceleratedSurface::EGLAcceleratedSurface(const gfx::Size& size)
237 : size_(size), texture_(0) {
238 Display* dpy = gfx::GLSurfaceEGL::GetNativeDisplay();
239 EGLDisplay edpy = gfx::GLSurfaceEGL::GetHardwareDisplay();
240
241 XID window = XDefaultRootWindow(dpy);
242 XWindowAttributes gwa;
243 bool success = XGetWindowAttributes(dpy, window, &gwa);
244 DCHECK(success);
245 pixmap_ = XCreatePixmap(
246 dpy, window, size_.width(), size_.height(), gwa.depth);
247
248 image_ = eglCreateImageKHR(
249 edpy, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
250 reinterpret_cast<void*>(pixmap_), NULL);
251
252 glGenTextures(1, &texture_);
253
254 GLint current_texture = 0;
255 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
256
257 glBindTexture(GL_TEXTURE_2D, texture_);
258 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
259 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
262 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
263
264 glBindTexture(GL_TEXTURE_2D, current_texture);
265 }
266
267 EGLAcceleratedSurface::~EGLAcceleratedSurface() {
268 glDeleteTextures(1, &texture_);
269 eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_);
270 XFreePixmap(gfx::GLSurfaceEGL::GetNativeDisplay(), pixmap_);
271 }
272
273 EGLImageTransportSurface::EGLImageTransportSurface(
274 GpuChannelManager* manager,
275 GpuCommandBufferStub* stub)
276 : gfx::PbufferGLSurfaceEGL(false, gfx::Size(16, 16)),
277 backbuffer_suggested_allocation_(true),
278 frontbuffer_suggested_allocation_(true),
279 fbo_id_(0),
280 made_current_(false) {
281 helper_.reset(new ImageTransportHelper(this,
282 manager,
283 stub,
284 gfx::kNullPluginWindow));
285 }
286
287 EGLImageTransportSurface::~EGLImageTransportSurface() {
288 Destroy();
289 }
290
291 bool EGLImageTransportSurface::Initialize() {
292 if (!helper_->Initialize())
293 return false;
294 return gfx::PbufferGLSurfaceEGL::Initialize();
295 }
296
297 void EGLImageTransportSurface::Destroy() {
298 if (back_surface_.get())
299 ReleaseSurface(&back_surface_);
300 if (front_surface_.get())
301 ReleaseSurface(&front_surface_);
302
303 helper_->Destroy();
304 gfx::PbufferGLSurfaceEGL::Destroy();
305 }
306
307 // Make sure that buffer swaps occur for the surface, so we can send the data
308 // to the actual onscreen surface in the browser
309 bool EGLImageTransportSurface::IsOffscreen() {
310 return false;
311 }
312
313 bool EGLImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
314 if (made_current_)
315 return true;
316
317 if (!context->HasExtension("EGL_KHR_image") &&
318 !context->HasExtension("EGL_KHR_image_pixmap")) {
319 DLOG(ERROR) << "EGLImage from X11 pixmap not supported";
320 return false;
321 }
322
323 glGenFramebuffersEXT(1, &fbo_id_);
324 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_);
325
326 // Creating 16x16 (instead of 1x1) to work around ARM Mali driver issue
327 // (see https://code.google.com/p/chrome-os-partner/issues/detail?id=9445)
328 OnResize(gfx::Size(16, 16));
329
330 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
331 if (status != GL_FRAMEBUFFER_COMPLETE) {
332 DLOG(ERROR) << "Framebuffer incomplete.";
333 return false;
334 }
335
336 made_current_ = true;
337 return true;
338 }
339
340 unsigned int EGLImageTransportSurface::GetBackingFrameBufferObject() {
341 return fbo_id_;
342 }
343
344 void EGLImageTransportSurface::SetBackbufferAllocation(bool allocated) {
345 if (backbuffer_suggested_allocation_ == allocated)
346 return;
347 backbuffer_suggested_allocation_ = allocated;
348
349 if (backbuffer_suggested_allocation_)
350 OnResize(visible_size_);
351 else
352 ReleaseSurface(&back_surface_);
353 }
354
355 void EGLImageTransportSurface::SetFrontbufferAllocation(bool allocated) {
356 if (frontbuffer_suggested_allocation_ == allocated)
357 return;
358 frontbuffer_suggested_allocation_ = allocated;
359 }
360
361 void EGLImageTransportSurface::ReleaseSurface(
362 scoped_refptr<EGLAcceleratedSurface>* surface) {
363 if (surface->get()) {
364 GpuHostMsg_AcceleratedSurfaceRelease_Params params;
365 params.identifier = (*surface)->pixmap();
366 helper_->SendAcceleratedSurfaceRelease(params);
367 *surface = NULL;
368 }
369 }
370
371 void EGLImageTransportSurface::OnResize(gfx::Size size) {
372 visible_size_ = size;
373 back_surface_ = new EGLAcceleratedSurface(size);
374
375 GLint previous_fbo_id = 0;
376 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previous_fbo_id);
377
378 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
379 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
380 GL_COLOR_ATTACHMENT0,
381 GL_TEXTURE_2D,
382 back_surface_->texture(),
383 0);
384 glFlush();
385
386 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id);
387
388 GpuHostMsg_AcceleratedSurfaceNew_Params params;
389 params.width = size.width();
390 params.height = size.height();
391 params.surface_handle = back_surface_->pixmap();
392 helper_->SendAcceleratedSurfaceNew(params);
393
394 helper_->SetScheduled(false);
395 }
396
397 bool EGLImageTransportSurface::SwapBuffers() {
398 DCHECK(backbuffer_suggested_allocation_);
399 if (!frontbuffer_suggested_allocation_)
400 return true;
401 front_surface_.swap(back_surface_);
402 DCHECK_NE(front_surface_.get(), static_cast<EGLAcceleratedSurface*>(NULL));
403 helper_->DeferToFence(base::Bind(
404 &EGLImageTransportSurface::SendBuffersSwapped,
405 AsWeakPtr()));
406
407 gfx::Size expected_size = front_surface_->size();
408 if (!back_surface_.get() || back_surface_->size() != expected_size) {
409 OnResize(expected_size);
410 } else {
411 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
412 GL_COLOR_ATTACHMENT0,
413 GL_TEXTURE_2D,
414 back_surface_->texture(),
415 0);
416 }
417 previous_damage_rect_ = gfx::Rect(front_surface_->size());
418 return true;
419 }
420
421 void EGLImageTransportSurface::SendBuffersSwapped() {
422 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
423 params.surface_handle = front_surface_->pixmap();
424 helper_->SendAcceleratedSurfaceBuffersSwapped(params);
425 helper_->SetScheduled(false);
426 }
427
428 bool EGLImageTransportSurface::PostSubBuffer(
429 int x, int y, int width, int height) {
430 DCHECK(backbuffer_suggested_allocation_);
431 if (!frontbuffer_suggested_allocation_)
432 return true;
433 // If we are recreating the frontbuffer with this swap, make sure we are
434 // drawing a full frame.
435 DCHECK(front_surface_.get() ||
436 (!x && !y && gfx::Size(width, height) == visible_size_));
437 DCHECK_NE(back_surface_.get(), static_cast<EGLAcceleratedSurface*>(NULL));
438 gfx::Size expected_size = back_surface_->size();
439 bool surfaces_same_size = front_surface_.get() &&
440 front_surface_->size() == expected_size;
441
442 const gfx::Rect new_damage_rect(x, y, width, height);
443
444 // An empty damage rect is a successful no-op.
445 if (new_damage_rect.IsEmpty())
446 return true;
447
448 if (surfaces_same_size) {
449 std::vector<gfx::Rect> regions_to_copy;
450 GetRegionsToCopy(previous_damage_rect_, new_damage_rect, &regions_to_copy);
451
452 GLint previous_texture_id = 0;
453 glGetIntegerv(GL_ACTIVE_TEXTURE, &previous_texture_id);
454 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
455 GL_COLOR_ATTACHMENT0,
456 GL_TEXTURE_2D,
457 front_surface_->texture(),
458 0);
459 glBindTexture(GL_TEXTURE_2D, back_surface_->texture());
460
461 for (size_t i = 0; i < regions_to_copy.size(); ++i) {
462 const gfx::Rect& region_to_copy = regions_to_copy[i];
463 if (!region_to_copy.IsEmpty()) {
464 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, region_to_copy.x(),
465 region_to_copy.y(), region_to_copy.x(), region_to_copy.y(),
466 region_to_copy.width(), region_to_copy.height());
467 }
468 }
469 glBindTexture(GL_TEXTURE_2D, previous_texture_id);
470 }
471
472 front_surface_.swap(back_surface_);
473
474 if (!surfaces_same_size) {
475 DCHECK(new_damage_rect == gfx::Rect(expected_size));
476 OnResize(expected_size);
477 }
478
479 helper_->DeferToFence(base::Bind(
480 &EGLImageTransportSurface::SendPostSubBuffer,
481 AsWeakPtr(), x, y, width, height));
482
483 previous_damage_rect_ = new_damage_rect;
484
485 return true;
486 }
487
488 void EGLImageTransportSurface::SendPostSubBuffer(
489 int x, int y, int width, int height) {
490 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
491 params.surface_handle = front_surface_->pixmap();
492 params.x = x;
493 params.y = y;
494 params.width = width;
495 params.height = height;
496
497 helper_->SendAcceleratedSurfacePostSubBuffer(params);
498 helper_->SetScheduled(false);
499 }
500
501 std::string EGLImageTransportSurface::GetExtensions() {
502 std::string extensions = gfx::GLSurface::GetExtensions();
503 extensions += extensions.empty() ? "" : " ";
504 extensions += "GL_CHROMIUM_front_buffer_cached ";
505 extensions += "GL_CHROMIUM_post_sub_buffer";
506 return extensions;
507 }
508
509 gfx::Size EGLImageTransportSurface::GetSize() {
510 return back_surface_->size();
511 }
512
513 void EGLImageTransportSurface::OnNewSurfaceACK(
514 uint64 surface_handle, TransportDIB::Handle /*shm_handle*/) {
515 DCHECK_EQ(back_surface_->pixmap(), surface_handle);
516 helper_->SetScheduled(true);
517 }
518
519 void EGLImageTransportSurface::OnBufferPresented(uint32 sync_point) {
520 helper_->SetScheduled(true);
521 }
522
523 void EGLImageTransportSurface::OnResizeViewACK() {
524 NOTREACHED();
525 }
526
527 GLXImageTransportSurface::GLXImageTransportSurface(
528 GpuChannelManager* manager,
529 GpuCommandBufferStub* stub)
530 : gfx::NativeViewGLSurfaceGLX(),
531 backbuffer_suggested_allocation_(true),
532 frontbuffer_suggested_allocation_(true),
533 dummy_parent_(0),
534 size_(1, 1),
535 bound_(false),
536 needs_resize_(false),
537 made_current_(false) {
538 helper_.reset(new ImageTransportHelper(this,
539 manager,
540 stub,
541 gfx::kNullPluginWindow));
542 }
543
544 GLXImageTransportSurface::~GLXImageTransportSurface() {
545 Destroy();
546 }
547
548 bool GLXImageTransportSurface::Initialize() {
549 // Create a dummy window to host the real window.
550 Display* dpy = static_cast<Display*>(GetDisplay());
551 ScopedDisplayLock lock(dpy);
552
553 XSetWindowAttributes swa;
554 swa.override_redirect = True;
555 dummy_parent_ = XCreateWindow(
556 dpy,
557 RootWindow(dpy, DefaultScreen(dpy)), // parent
558 -100, -100, 1, 1,
559 0, // border width
560 CopyFromParent, // depth
561 InputOutput,
562 CopyFromParent, // visual
563 CWOverrideRedirect, &swa);
564 XMapWindow(dpy, dummy_parent_);
565
566 swa.event_mask = StructureNotifyMask;
567 swa.override_redirect = false;
568 window_ = XCreateWindow(dpy,
569 dummy_parent_,
570 0, 0, size_.width(), size_.height(),
571 0, // border width
572 CopyFromParent, // depth
573 InputOutput,
574 CopyFromParent, // visual
575 CWEventMask, &swa);
576 XMapWindow(dpy, window_);
577 while (1) {
578 XEvent event;
579 XWindowEvent(dpy, window_, StructureNotifyMask, &event);
580 if (event.type == MapNotify && event.xmap.window == window_)
581 break;
582 }
583 XSelectInput(dpy, window_, NoEventMask);
584
585 // Manual setting must be used to avoid unnecessary rendering by server.
586 XCompositeRedirectWindow(dpy, window_, CompositeRedirectManual);
587 OnResize(size_);
588
589 if (!helper_->Initialize())
590 return false;
591 return gfx::NativeViewGLSurfaceGLX::Initialize();
592 }
593
594 void GLXImageTransportSurface::Destroy() {
595 if (bound_)
596 ReleaseSurface();
597
598 if (window_) {
599 Display* dpy = static_cast<Display*>(GetDisplay());
600 XDestroyWindow(dpy, window_);
601 XDestroyWindow(dpy, dummy_parent_);
602 }
603
604 helper_->Destroy();
605 gfx::NativeViewGLSurfaceGLX::Destroy();
606 }
607
608 void GLXImageTransportSurface::ReleaseSurface() {
609 DCHECK(bound_);
610 GpuHostMsg_AcceleratedSurfaceRelease_Params params;
611 params.identifier = window_;
612 helper_->SendAcceleratedSurfaceRelease(params);
613 bound_ = false;
614 }
615
616 void GLXImageTransportSurface::SetBackbufferAllocation(bool allocated) {
617 if (backbuffer_suggested_allocation_ == allocated)
618 return;
619 backbuffer_suggested_allocation_ = allocated;
620
621 if (backbuffer_suggested_allocation_)
622 ResizeSurface(size_);
623 else
624 ResizeSurface(gfx::Size(1,1));
625 }
626
627 void GLXImageTransportSurface::SetFrontbufferAllocation(bool allocated) {
628 if (frontbuffer_suggested_allocation_ == allocated)
629 return;
630 frontbuffer_suggested_allocation_ = allocated;
631
632 // We recreate frontbuffer by recreating backbuffer and swapping.
633 // But we release frontbuffer by telling UI to release its handle on it.
634 if (!frontbuffer_suggested_allocation_ && bound_)
635 ReleaseSurface();
636 }
637
638 void GLXImageTransportSurface::ResizeSurface(gfx::Size size) {
639 Display* dpy = static_cast<Display*>(GetDisplay());
640 XResizeWindow(dpy, window_, size.width(), size.height());
641 glXWaitX();
642 // Seems necessary to perform a swap after a resize
643 // in order to resize the front and back buffers (Intel driver bug).
644 // This doesn't always happen with scissoring enabled, so do it now.
645 if (gfx::g_GLX_MESA_copy_sub_buffer && gfx::GLSurface::GetCurrent() == this)
646 gfx::NativeViewGLSurfaceGLX::SwapBuffers();
647 needs_resize_ = true;
648 }
649
650 void GLXImageTransportSurface::OnResize(gfx::Size size) {
651 TRACE_EVENT0("gpu", "GLXImageTransportSurface::OnResize");
652 size_ = size;
653 ResizeSurface(size_);
654 }
655
656 bool GLXImageTransportSurface::SwapBuffers() {
657 DCHECK(backbuffer_suggested_allocation_);
658 if (!frontbuffer_suggested_allocation_)
659 return true;
660 gfx::NativeViewGLSurfaceGLX::SwapBuffers();
661 helper_->DeferToFence(base::Bind(
662 &GLXImageTransportSurface::SendBuffersSwapped,
663 AsWeakPtr()));
664
665 if (needs_resize_) {
666 GpuHostMsg_AcceleratedSurfaceNew_Params params;
667 params.width = size_.width();
668 params.height = size_.height();
669 params.surface_handle = window_;
670 helper_->SendAcceleratedSurfaceNew(params);
671 bound_ = true;
672 needs_resize_ = false;
673 }
674 return true;
675 }
676
677 void GLXImageTransportSurface::SendBuffersSwapped() {
678 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
679 params.surface_handle = window_;
680 helper_->SendAcceleratedSurfaceBuffersSwapped(params);
681 helper_->SetScheduled(false);
682 }
683
684 bool GLXImageTransportSurface::PostSubBuffer(
685 int x, int y, int width, int height) {
686 DCHECK(backbuffer_suggested_allocation_);
687 if (!frontbuffer_suggested_allocation_)
688 return true;
689 gfx::NativeViewGLSurfaceGLX::PostSubBuffer(x, y, width, height);
690 helper_->DeferToFence(base::Bind(
691 &GLXImageTransportSurface::SendPostSubBuffer,
692 AsWeakPtr(), x, y, width, height));
693
694 if (needs_resize_) {
695 GpuHostMsg_AcceleratedSurfaceNew_Params params;
696 params.width = size_.width();
697 params.height = size_.height();
698 params.surface_handle = window_;
699 helper_->SendAcceleratedSurfaceNew(params);
700 bound_ = true;
701 needs_resize_ = false;
702 }
703 return true;
704 }
705
706 void GLXImageTransportSurface::SendPostSubBuffer(
707 int x, int y, int width, int height) {
708 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
709 params.surface_handle = window_;
710 params.x = x;
711 params.y = y;
712 params.width = width;
713 params.height = height;
714
715 helper_->SendAcceleratedSurfacePostSubBuffer(params);
716 helper_->SetScheduled(false);
717 }
718
719 std::string GLXImageTransportSurface::GetExtensions() {
720 std::string extensions = gfx::NativeViewGLSurfaceGLX::GetExtensions();
721 extensions += extensions.empty() ? "" : " ";
722 extensions += "GL_CHROMIUM_front_buffer_cached";
723 return extensions;
724 }
725
726 gfx::Size GLXImageTransportSurface::GetSize() {
727 return size_;
728 }
729
730 bool GLXImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
731 if (made_current_)
732 return true;
733
734 // Check for driver support.
735 Display* dpy = static_cast<Display*>(GetDisplay());
736 int event_base, error_base;
737 if (XCompositeQueryExtension(dpy, &event_base, &error_base)) {
738 int major = 0, minor = 2;
739 XCompositeQueryVersion(dpy, &major, &minor);
740 if (major == 0 && minor < 2) {
741 DLOG(ERROR) << "Pixmap from window not supported.";
742 return false;
743 }
744 }
745
746 context->SetSwapInterval(0);
747
748 made_current_ = true;
749 return true;
750 }
751
752 void GLXImageTransportSurface::OnNewSurfaceACK(
753 uint64 surface_handle, TransportDIB::Handle /*shm_handle*/) {
754 }
755
756 void GLXImageTransportSurface::OnBufferPresented(uint32 sync_point) {
757 helper_->SetScheduled(true);
758 }
759
760 void GLXImageTransportSurface::OnResizeViewACK() {
761 NOTREACHED();
762 }
763
764 OSMesaImageTransportSurface::OSMesaImageTransportSurface(
765 GpuChannelManager* manager,
766 GpuCommandBufferStub* stub)
767 : gfx::GLSurfaceOSMesa(OSMESA_RGBA, gfx::Size(1, 1)),
768 size_(gfx::Size(1, 1)) {
769 helper_.reset(new ImageTransportHelper(this,
770 manager,
771 stub,
772 gfx::kNullPluginWindow));
773 }
774
775 OSMesaImageTransportSurface::~OSMesaImageTransportSurface() {
776 Destroy();
777 }
778
779 bool OSMesaImageTransportSurface::Initialize() {
780 if (!helper_->Initialize())
781 return false;
782 return gfx::GLSurfaceOSMesa::Initialize();
783 }
784
785 void OSMesaImageTransportSurface::Destroy() {
786 if (shared_mem_.get())
787 ReleaseSurface();
788
789 helper_->Destroy();
790 gfx::GLSurfaceOSMesa::Destroy();
791 }
792
793 // Make sure that buffer swaps occur for the surface, so we can send the data
794 // to the actual onscreen surface in the browser
795 bool OSMesaImageTransportSurface::IsOffscreen() {
796 return false;
797 }
798
799 void OSMesaImageTransportSurface::ReleaseSurface() {
800 GpuHostMsg_AcceleratedSurfaceRelease_Params params;
801 params.identifier = shared_id_;
802 helper_->SendAcceleratedSurfaceRelease(params);
803
804 shared_mem_.reset();
805 shared_id_ = 0;
806 }
807
808 void OSMesaImageTransportSurface::OnResize(gfx::Size size) {
809 shared_mem_.reset();
810 shared_id_ = 0;
811
812 GLSurfaceOSMesa::Resize(size);
813
814 // Now that we resized/reallocated the memory buffer, we need to change
815 // what OSMesa is pointing at to the new buffer.
816 helper_->MakeCurrent();
817
818 size_ = size;
819
820 GpuHostMsg_AcceleratedSurfaceNew_Params params;
821 params.width = size_.width();
822 params.height = size_.height();
823 params.surface_handle = 0; // id comes from the browser with the shared mem
824 helper_->SendAcceleratedSurfaceNew(params);
825
826 helper_->SetScheduled(false);
827 }
828
829 void OSMesaImageTransportSurface::OnNewSurfaceACK(
830 uint64 surface_handle, TransportDIB::Handle shm_handle) {
831 shared_id_ = surface_handle;
832 shared_mem_.reset(TransportDIB::Map(shm_handle));
833 DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL));
834
835 helper_->SetScheduled(true);
836 }
837
838 void OSMesaImageTransportSurface::OnResizeViewACK() {
839 NOTREACHED();
840 }
841
842 bool OSMesaImageTransportSurface::SwapBuffers() {
843 DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL));
844
845 // Copy the OSMesa buffer to the shared memory
846 glFinish();
847 memcpy(shared_mem_->memory(), GetHandle(), size_.GetArea() * 4);
848
849 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
850 params.surface_handle = shared_id_;
851 helper_->SendAcceleratedSurfaceBuffersSwapped(params);
852
853 helper_->SetScheduled(false);
854 return true;
855 }
856
857 bool OSMesaImageTransportSurface::PostSubBuffer(
858 int x, int y, int width, int height) {
859 DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL));
860
861 // Copy the OSMesa buffer to the shared memory
862 glFinish();
863
864 int flipped_y = GetSize().height() - y - height;
865
866 for (int row = 0; row < height; ++row) {
867 int mem_offset = ((flipped_y + row) * size_.width() + x);
868 int32* dest_address = static_cast<int32*>(shared_mem_->memory()) +
869 mem_offset;
870 int32* src_address = static_cast<int32*>(GetHandle()) + mem_offset;
871 memcpy(dest_address, src_address, width * 4);
872 }
873
874 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
875 params.surface_handle = shared_id_;
876 params.x = x;
877 params.y = y;
878 params.width = width;
879 params.height = height;
880 helper_->SendAcceleratedSurfacePostSubBuffer(params);
881
882 helper_->SetScheduled(false);
883 return true;
884 }
885
886 std::string OSMesaImageTransportSurface::GetExtensions() {
887 std::string extensions = gfx::GLSurface::GetExtensions();
888 extensions += extensions.empty() ? "" : " ";
889 extensions += "GL_CHROMIUM_front_buffer_cached ";
890 extensions += "GL_CHROMIUM_post_sub_buffer";
891 return extensions;
892 }
893
894 void OSMesaImageTransportSurface::OnBufferPresented(uint32 sync_point) {
895 helper_->SetScheduled(true);
896 }
897
898 gfx::Size OSMesaImageTransportSurface::GetSize() {
899 return size_;
900 }
901
902 } // namespace
903 8
904 // static 9 // static
905 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( 10 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
906 GpuChannelManager* manager, 11 GpuChannelManager* manager,
907 GpuCommandBufferStub* stub, 12 GpuCommandBufferStub* stub,
908 const gfx::GLSurfaceHandle& handle) { 13 const gfx::GLSurfaceHandle& handle) {
909 scoped_refptr<gfx::GLSurface> surface; 14 scoped_refptr<gfx::GLSurface> surface;
910 if (!handle.handle) { 15 if (!handle.handle) {
911 DCHECK(handle.transport); 16 DCHECK(handle.transport);
912 if (!handle.parent_client_id) { 17 DCHECK(handle.parent_client_id);
913 switch (gfx::GetGLImplementation()) { 18 surface = new TextureImageTransportSurface(manager, stub, handle);
914 case gfx::kGLImplementationDesktopGL:
915 surface = new GLXImageTransportSurface(manager, stub);
916 break;
917 case gfx::kGLImplementationEGLGLES2:
918 surface = new EGLImageTransportSurface(manager, stub);
919 break;
920 case gfx::kGLImplementationOSMesaGL:
921 surface = new OSMesaImageTransportSurface(manager, stub);
922 break;
923 default:
924 NOTREACHED();
925 return NULL;
926 }
927 } else {
928 surface = new TextureImageTransportSurface(manager, stub, handle);
929 }
930 } else { 19 } else {
931 surface = gfx::GLSurface::CreateViewGLSurface(false, handle.handle); 20 surface = gfx::GLSurface::CreateViewGLSurface(false, handle.handle);
932 if (!surface.get()) 21 if (!surface.get())
933 return NULL; 22 return NULL;
934 surface = new PassThroughImageTransportSurface(manager, 23 surface = new PassThroughImageTransportSurface(manager,
935 stub, 24 stub,
936 surface.get(), 25 surface.get(),
937 handle.transport); 26 handle.transport);
938 } 27 }
939 28
940 if (surface->Initialize()) 29 if (surface->Initialize())
941 return surface; 30 return surface;
942 else 31 else
943 return NULL; 32 return NULL;
944 } 33 }
OLDNEW
« no previous file with comments | « content/common/gpu/image_transport_surface.cc ('k') | content/common/gpu/image_transport_surface_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698