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

Side by Side Diff: content/browser/renderer_host/accelerated_surface_container_linux.cc

Issue 8307001: Enable accelerated compositing of web pages when using webkit compositor (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: rebase Created 9 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
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 #include "content/browser/renderer_host/accelerated_surface_container_linux.h"
6
7 #include <X11/Xlib.h>
8 #include <X11/extensions/Xcomposite.h>
9
10 #include "base/lazy_instance.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "third_party/angle/include/EGL/egl.h"
13 #include "third_party/angle/include/EGL/eglext.h"
14 #include "ui/gfx/gl/gl_bindings.h"
15 #include "ui/gfx/gl/gl_implementation.h"
16 #include "ui/gfx/gl/gl_surface_egl.h"
17 #include "ui/gfx/gl/gl_surface_glx.h"
18 #include "ui/gfx/rect.h"
19 #include "ui/gfx/transform.h"
20
21 namespace {
22
23 class AcceleratedSurfaceContainerLinuxEGL
24 : public AcceleratedSurfaceContainerLinux {
25 public:
26 explicit AcceleratedSurfaceContainerLinuxEGL(const gfx::Size& size);
27
28 virtual bool Initialize(uint64* surface_id) OVERRIDE;
29
30 // TextureGL implementation
31 virtual void Draw(const ui::TextureDrawParams& params,
32 const gfx::Rect& clip_bounds_in_texture) OVERRIDE;
33
34 private:
35 virtual ~AcceleratedSurfaceContainerLinuxEGL();
36
37 void* image_;
38
39 DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxEGL);
40 };
41
42 class AcceleratedSurfaceContainerLinuxGLX
43 : public AcceleratedSurfaceContainerLinux {
44 public:
45 explicit AcceleratedSurfaceContainerLinuxGLX(const gfx::Size& size);
46
47 virtual bool Initialize(uint64* surface_id) OVERRIDE;
48
49 // TextureGL implementation
50 virtual void Draw(const ui::TextureDrawParams& params,
51 const gfx::Rect& clip_bounds_in_texture) OVERRIDE;
52
53 protected:
54 static bool InitializeOneOff();
55
56 static base::LazyInstance<GLXFBConfig> fbconfig_;
57
58 private:
59 virtual ~AcceleratedSurfaceContainerLinuxGLX();
60
61 XID pixmap_;
62 XID glx_pixmap_;
63
64 DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxGLX);
65 };
66
67 class AcceleratedSurfaceContainerLinuxOSMesa
68 : public AcceleratedSurfaceContainerLinux {
69 public:
70 explicit AcceleratedSurfaceContainerLinuxOSMesa(const gfx::Size& size);
71
72 virtual bool Initialize(uint64* surface_id) OVERRIDE;
73
74 // TextureGL implementation
75 virtual void Draw(const ui::TextureDrawParams& params,
76 const gfx::Rect& clip_bounds_in_texture) OVERRIDE;
77
78 // Some implementations of this class use shared memory, this gives the handle
79 // to the shared buffer, which is part of the surface container.
80 // When shared memory is not used, this will return
81 // TransportDIB::DefaultHandleValue().
82 virtual TransportDIB::Handle Handle() const OVERRIDE;
83
84 private:
85 virtual ~AcceleratedSurfaceContainerLinuxOSMesa();
86
87 scoped_ptr<TransportDIB> shared_mem_;
88
89 DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerLinuxOSMesa);
90 };
91
92 class ScopedPtrXFree {
93 public:
94 void operator()(void* x) const {
95 ::XFree(x);
96 }
97 };
98
99 // static
100 base::LazyInstance<GLXFBConfig> AcceleratedSurfaceContainerLinuxGLX::fbconfig_(
101 base::LINKER_INITIALIZED);
102
103 AcceleratedSurfaceContainerLinuxEGL::AcceleratedSurfaceContainerLinuxEGL(
104 const gfx::Size& size)
105 : AcceleratedSurfaceContainerLinux(size),
106 image_(NULL) {
107 }
108
109 bool AcceleratedSurfaceContainerLinuxEGL::Initialize(uint64* surface_id) {
110 ui::SharedResources* instance = ui::SharedResources::GetInstance();
111 DCHECK(instance);
112 instance->MakeSharedContextCurrent();
113
114 image_ = eglCreateImageKHR(
115 gfx::GLSurfaceEGL::GetHardwareDisplay(), EGL_NO_CONTEXT,
116 EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<void*>(*surface_id), NULL);
117
118 glGenTextures(1, &texture_id_);
119 glBindTexture(GL_TEXTURE_2D, texture_id_);
120 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
121 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
124 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
125 glFlush();
126
127 return true;
128 }
129
130 AcceleratedSurfaceContainerLinuxEGL::~AcceleratedSurfaceContainerLinuxEGL() {
131 ui::SharedResources* instance = ui::SharedResources::GetInstance();
132 DCHECK(instance);
133 instance->MakeSharedContextCurrent();
134
135 eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_);
136 glFlush();
137 }
138
139 void AcceleratedSurfaceContainerLinuxEGL::Draw(
140 const ui::TextureDrawParams& params,
141 const gfx::Rect& clip_bounds_in_texture) {
142 ui::SharedResources* instance = ui::SharedResources::GetInstance();
143 DCHECK(instance);
144
145 ui::TextureDrawParams modified_params = params;
146 modified_params.vertically_flipped = true;
147
148 DrawInternal(*instance->program_no_swizzle(),
149 modified_params,
150 clip_bounds_in_texture);
151 }
152
153 AcceleratedSurfaceContainerLinuxGLX::AcceleratedSurfaceContainerLinuxGLX(
154 const gfx::Size& size)
155 : AcceleratedSurfaceContainerLinux(size),
156 pixmap_(0),
157 glx_pixmap_(0) {
158 }
159
160 bool AcceleratedSurfaceContainerLinuxGLX::Initialize(uint64* surface_id) {
161 ui::SharedResources* instance = ui::SharedResources::GetInstance();
162 DCHECK(instance);
163 instance->MakeSharedContextCurrent();
164
165 if (!AcceleratedSurfaceContainerLinuxGLX::InitializeOneOff())
166 return false;
167
168 // Create pixmap from window.
169 // We receive a window here rather than a pixmap directly because drivers
170 // require (or required) that the pixmap used to create the GL texture be
171 // created in the same process as the texture.
172 Display* dpy = gfx::GLSurfaceGLX::GetDisplay();
173 pixmap_ = XCompositeNameWindowPixmap(dpy, *surface_id);
174
175 // Wrap the pixmap in a GLXPixmap
176 const int pixmapAttribs[] = {
177 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
178 GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
179 0
180 };
181
182 glx_pixmap_ = glXCreatePixmap(
183 dpy, fbconfig_.Get(), pixmap_, pixmapAttribs);
184
185 // Create texture.
186 glGenTextures(1, &texture_id_);
187 glBindTexture(GL_TEXTURE_2D, texture_id_);
188 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
189 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
190 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
192
193 return true;
194 }
195
196 AcceleratedSurfaceContainerLinuxGLX::~AcceleratedSurfaceContainerLinuxGLX() {
197 ui::SharedResources* instance = ui::SharedResources::GetInstance();
198 DCHECK(instance);
199 instance->MakeSharedContextCurrent();
200
201 Display* dpy = gfx::GLSurfaceGLX::GetDisplay();
202 if (glx_pixmap_)
203 glXDestroyGLXPixmap(dpy, glx_pixmap_);
204 if (pixmap_)
205 XFreePixmap(dpy, pixmap_);
206 }
207
208 void AcceleratedSurfaceContainerLinuxGLX::Draw(
209 const ui::TextureDrawParams& params,
210 const gfx::Rect& clip_bounds_in_texture) {
211 ui::SharedResources* instance = ui::SharedResources::GetInstance();
212 DCHECK(instance);
213
214 Display* dpy = gfx::GLSurfaceGLX::GetDisplay();
215
216 glBindTexture(GL_TEXTURE_2D, texture_id_);
217 glXBindTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
218 DrawInternal(*instance->program_no_swizzle(),
219 params,
220 clip_bounds_in_texture);
221 glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT);
222 }
223
224 // static
225 bool AcceleratedSurfaceContainerLinuxGLX::InitializeOneOff()
226 {
227 static bool initialized = false;
228 if (initialized)
229 return true;
230
231 Display* dpy = gfx::GLSurfaceGLX::GetDisplay();
232 int event_base, error_base;
233 if (XCompositeQueryExtension(dpy, &event_base, &error_base)) {
234 int major = 0, minor = 2;
235 XCompositeQueryVersion(dpy, &major, &minor);
236 if (major == 0 && minor < 2) {
237 LOG(ERROR) << "Pixmap from window not supported.";
238 return false;
239 }
240 }
241
242 // Wrap the pixmap in a GLXPixmap
243 int screen = DefaultScreen(dpy);
244 XWindowAttributes gwa;
245 XGetWindowAttributes(dpy, RootWindow(dpy, screen), &gwa);
246 unsigned int visualid = XVisualIDFromVisual(gwa.visual);
247
248 int nfbconfigs, config;
249 scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> fbconfigs(
250 glXGetFBConfigs(dpy, screen, &nfbconfigs));
251
252 for (config = 0; config < nfbconfigs; config++) {
253 XVisualInfo* visinfo = glXGetVisualFromFBConfig(
254 dpy, fbconfigs.get()[config]);
255 if (!visinfo || visinfo->visualid != visualid)
256 continue;
257
258 int value;
259 glXGetFBConfigAttrib(dpy,
260 fbconfigs.get()[config],
261 GLX_DRAWABLE_TYPE,
262 &value);
263 if (!(value & GLX_PIXMAP_BIT))
264 continue;
265
266 glXGetFBConfigAttrib(dpy,
267 fbconfigs.get()[config],
268 GLX_BIND_TO_TEXTURE_TARGETS_EXT,
269 &value);
270 if (!(value & GLX_TEXTURE_2D_BIT_EXT))
271 continue;
272
273 glXGetFBConfigAttrib(dpy,
274 fbconfigs.get()[config],
275 GLX_BIND_TO_TEXTURE_RGB_EXT,
276 &value);
277 if (value == GL_FALSE)
278 continue;
279
280 break;
281 }
282
283 if (config == nfbconfigs) {
284 LOG(ERROR)
285 << "Could not find configuration suitable for binding a pixmap "
286 << "as a texture.";
287 return false;
288 }
289
290 fbconfig_.Get() = fbconfigs.get()[config];
291
292 initialized = true;
293 return initialized;
294 }
295
296 AcceleratedSurfaceContainerLinuxOSMesa::AcceleratedSurfaceContainerLinuxOSMesa(
297 const gfx::Size& size)
298 : AcceleratedSurfaceContainerLinux(size) {
299 }
300
301 bool AcceleratedSurfaceContainerLinuxOSMesa::Initialize(uint64* surface_id) {
302 static uint32 next_id = 1;
303
304 ui::SharedResources* instance = ui::SharedResources::GetInstance();
305 DCHECK(instance);
306 instance->MakeSharedContextCurrent();
307
308 // We expect to make the id here, so don't want the other end giving us one
309 DCHECK_EQ(*surface_id, static_cast<uint64>(0));
310
311 // It's possible that this ID gneration could clash with IDs from other
312 // AcceleratedSurfaceContainerLinux* objects, however we should never have
313 // ids active from more than one type at the same time, so we have free
314 // reign of the id namespace.
315 *surface_id = next_id++;
316
317 shared_mem_.reset(
318 TransportDIB::Create(size_.GetArea() * 4, // GL_RGBA=4 B/px
319 *surface_id));
320 // Create texture.
321 glGenTextures(1, &texture_id_);
322 glBindTexture(GL_TEXTURE_2D, texture_id_);
323 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
324 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
327
328 // we generate the ID to be used here.
329 return true;
330 }
331
332 void AcceleratedSurfaceContainerLinuxOSMesa::Draw(
333 const ui::TextureDrawParams& params,
334 const gfx::Rect& clip_bounds_in_texture) {
335 ui::SharedResources* instance = ui::SharedResources::GetInstance();
336 DCHECK(instance);
337
338 if (shared_mem_.get()) {
339 glBindTexture(GL_TEXTURE_2D, texture_id_);
340 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
341 size_.width(), size_.height(), 0,
342 GL_RGBA, GL_UNSIGNED_BYTE, shared_mem_->memory());
343
344 DrawInternal(*instance->program_no_swizzle(),
345 params,
346 clip_bounds_in_texture);
347 }
348 }
349
350 TransportDIB::Handle AcceleratedSurfaceContainerLinuxOSMesa::Handle() const {
351 if (shared_mem_.get())
352 return shared_mem_->handle();
353 else
354 return TransportDIB::DefaultHandleValue();
355 }
356
357 AcceleratedSurfaceContainerLinuxOSMesa::
358 ~AcceleratedSurfaceContainerLinuxOSMesa() {
359 }
360
361 } // namespace
362
363 AcceleratedSurfaceContainerLinux::AcceleratedSurfaceContainerLinux(
364 const gfx::Size& size) : TextureGL(size) {
365 }
366
367 TransportDIB::Handle AcceleratedSurfaceContainerLinux::Handle() const {
368 return TransportDIB::DefaultHandleValue();
369 }
370
371 // static
372 AcceleratedSurfaceContainerLinux*
373 AcceleratedSurfaceContainerLinux::CreateAcceleratedSurfaceContainer(
374 const gfx::Size& size) {
375 switch (gfx::GetGLImplementation()) {
376 case gfx::kGLImplementationDesktopGL:
377 return new AcceleratedSurfaceContainerLinuxGLX(size);
378 case gfx::kGLImplementationEGLGLES2:
379 return new AcceleratedSurfaceContainerLinuxEGL(size);
380 case gfx::kGLImplementationOSMesaGL:
381 return new AcceleratedSurfaceContainerLinuxOSMesa(size);
382 default:
383 NOTREACHED();
384 return NULL;
385 }
386 }
387
388 void AcceleratedSurfaceContainerLinux::SetCanvas(
389 const SkCanvas& canvas,
390 const gfx::Point& origin,
391 const gfx::Size& overall_size) {
392 NOTREACHED();
393 }
394
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698