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

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

Issue 10689108: Aura: Have ui::Layer implement WebKit::WebExternalTextureLayerClient (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Nuke TestImageTransportFactory. 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/image_transport_client.h"
6
7 #include <X11/Xlib.h>
8 #include <X11/extensions/Xcomposite.h>
9
10 #include "base/debug/trace_event.h"
11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop.h"
14 #include "content/browser/renderer_host/image_transport_factory.h"
15 #include "third_party/angle/include/EGL/egl.h"
16 #include "third_party/angle/include/EGL/eglext.h"
17 #include "ui/gfx/size.h"
18 #include "ui/gl/gl_bindings.h"
19 #include "ui/gl/gl_implementation.h"
20 #include "ui/gl/gl_surface_egl.h"
21 #include "ui/gl/gl_surface_glx.h"
22 #include "ui/gl/scoped_make_current.h"
23
24 namespace {
25
26 class ScopedPtrXFree {
27 public:
28 void operator()(void* x) const {
29 ::XFree(x);
30 }
31 };
32
33 GLuint CreateTexture() {
34 GLuint texture;
35 glGenTextures(1, &texture);
36 glBindTexture(GL_TEXTURE_2D, texture);
37 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
38 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
39 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
40 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
41 return texture;
42 }
43
44 class ImageTransportClientEGL : public ImageTransportClient {
45 public:
46 ImageTransportClientEGL(ImageTransportFactory* factory, const gfx::Size& size)
47 : ImageTransportClient(true, size),
48 factory_(factory),
49 image_(NULL) {
50 }
51
52 virtual bool Initialize(uint64* surface_handle) OVERRIDE {
53 scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent());
54 image_ = eglCreateImageKHR(
55 gfx::GLSurfaceEGL::GetHardwareDisplay(), EGL_NO_CONTEXT,
56 EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<void*>(*surface_handle), NULL);
57 if (!image_)
58 return false;
59 set_texture_id(CreateTexture());
60 glBindTexture(GL_TEXTURE_2D, texture_id());
61 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
62 glFlush();
63 return true;
64 }
65
66 virtual void Update() OVERRIDE {}
67 virtual TransportDIB::Handle Handle() const OVERRIDE {
68 return TransportDIB::DefaultHandleValue();
69 }
70
71 protected:
72 virtual ~ImageTransportClientEGL() {
73 scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent());
74 if (image_)
75 eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), image_);
76 unsigned int texture = texture_id();
77 if (texture)
78 glDeleteTextures(1, &texture);
79 glFlush();
80 }
81
82 private:
83 ImageTransportFactory* factory_;
84 EGLImageKHR image_;
85 };
86
87 class ImageTransportClientGLX : public ImageTransportClient {
88 public:
89 ImageTransportClientGLX(ImageTransportFactory* factory, const gfx::Size& size)
90 : ImageTransportClient(false, size),
91 factory_(factory),
92 pixmap_(0),
93 glx_pixmap_(0),
94 acquired_(false) {
95 }
96
97 virtual bool Initialize(uint64* surface_handle) OVERRIDE {
98 TRACE_EVENT0("renderer_host", "ImageTransportClientGLX::Initialize");
99 Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay();
100
101 scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent());
102 if (!InitializeOneOff(dpy))
103 return false;
104
105 // Create pixmap from window.
106 // We receive a window here rather than a pixmap directly because drivers
107 // require (or required) that the pixmap used to create the GL texture be
108 // created in the same process as the texture.
109 pixmap_ = XCompositeNameWindowPixmap(dpy, *surface_handle);
110
111 const int pixmapAttribs[] = {
112 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
113 GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
114 0
115 };
116
117 glx_pixmap_ = glXCreatePixmap(dpy, fbconfig_.Get(), pixmap_, pixmapAttribs);
118
119 set_texture_id(CreateTexture());
120 glFlush();
121 return true;
122 }
123
124 virtual void Update() OVERRIDE {
125 TRACE_EVENT0("renderer_host", "ImageTransportClientGLX::Update");
126 Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay();
127 scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent());
128 glBindTexture(GL_TEXTURE_2D, texture_id());
129 if (acquired_)
130 glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT);
131 glXBindTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
132 acquired_ = true;
133 glFlush();
134 }
135
136 virtual TransportDIB::Handle Handle() const OVERRIDE {
137 return TransportDIB::DefaultHandleValue();
138 }
139
140 protected:
141 virtual ~ImageTransportClientGLX() {
142 scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent());
143 Display* dpy = base::MessagePumpForUI::GetDefaultXDisplay();
144 if (glx_pixmap_) {
145 if (acquired_)
146 glXReleaseTexImageEXT(dpy, glx_pixmap_, GLX_FRONT_LEFT_EXT);
147 glXDestroyGLXPixmap(dpy, glx_pixmap_);
148 }
149 if (pixmap_)
150 XFreePixmap(dpy, pixmap_);
151 unsigned int texture = texture_id();
152 if (texture)
153 glDeleteTextures(1, &texture);
154 glFlush();
155 }
156
157 private:
158 static bool InitializeOneOff(Display* dpy) {
159 static bool initialized = false;
160 if (initialized)
161 return true;
162
163 int event_base, error_base;
164 if (XCompositeQueryExtension(dpy, &event_base, &error_base)) {
165 int major = 0, minor = 2;
166 XCompositeQueryVersion(dpy, &major, &minor);
167 if (major == 0 && minor < 2) {
168 LOG(ERROR) << "Pixmap from window not supported.";
169 return false;
170 }
171 }
172 // Wrap the pixmap in a GLXPixmap
173 int screen = DefaultScreen(dpy);
174 XWindowAttributes gwa;
175 XGetWindowAttributes(dpy, RootWindow(dpy, screen), &gwa);
176 unsigned int visualid = XVisualIDFromVisual(gwa.visual);
177
178 int nfbconfigs, config;
179 scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> fbconfigs(
180 glXGetFBConfigs(dpy, screen, &nfbconfigs));
181
182 for (config = 0; config < nfbconfigs; config++) {
183 XVisualInfo* visinfo = glXGetVisualFromFBConfig(
184 dpy, fbconfigs.get()[config]);
185 if (!visinfo || visinfo->visualid != visualid)
186 continue;
187
188 int value;
189 glXGetFBConfigAttrib(dpy,
190 fbconfigs.get()[config],
191 GLX_DRAWABLE_TYPE,
192 &value);
193 if (!(value & GLX_PIXMAP_BIT))
194 continue;
195
196 glXGetFBConfigAttrib(dpy,
197 fbconfigs.get()[config],
198 GLX_BIND_TO_TEXTURE_TARGETS_EXT,
199 &value);
200 if (!(value & GLX_TEXTURE_2D_BIT_EXT))
201 continue;
202
203 glXGetFBConfigAttrib(dpy,
204 fbconfigs.get()[config],
205 GLX_BIND_TO_TEXTURE_RGB_EXT,
206 &value);
207 if (value == GL_FALSE)
208 continue;
209
210 break;
211 }
212
213 if (config == nfbconfigs) {
214 LOG(ERROR)
215 << "Could not find configuration suitable for binding a pixmap "
216 << "as a texture.";
217 return false;
218 }
219 fbconfig_.Get() = fbconfigs.get()[config];
220 initialized = true;
221 return initialized;
222 }
223
224 ImageTransportFactory* factory_;
225 XID pixmap_;
226 XID glx_pixmap_;
227 bool acquired_;
228 static base::LazyInstance<GLXFBConfig> fbconfig_;
229 };
230
231 base::LazyInstance<GLXFBConfig> ImageTransportClientGLX::fbconfig_ =
232 LAZY_INSTANCE_INITIALIZER;
233
234 class ImageTransportClientOSMesa : public ImageTransportClient {
235 public:
236 ImageTransportClientOSMesa(ImageTransportFactory* factory,
237 const gfx::Size& size)
238 : ImageTransportClient(false, size),
239 factory_(factory) {
240 }
241
242 virtual bool Initialize(uint64* surface_handle) OVERRIDE {
243 // We expect to make the handle here, so don't want the other end giving us
244 // one.
245 DCHECK_EQ(*surface_handle, static_cast<uint64>(0));
246
247 // It's possible that this ID gneration could clash with IDs from other
248 // AcceleratedSurfaceContainerTouch* objects, however we should never have
249 // ids active from more than one type at the same time, so we have free
250 // reign of the id namespace.
251 *surface_handle = next_handle_++;
252
253 shared_mem_.reset(
254 TransportDIB::Create(size().GetArea() * 4, // GL_RGBA=4 B/px
255 *surface_handle));
256 if (!shared_mem_.get())
257 return false;
258
259 scoped_ptr<gfx::ScopedMakeCurrent> bind(factory_->GetScopedMakeCurrent());
260 set_texture_id(CreateTexture());
261 glFlush();
262 return true;
263 }
264
265 virtual void Update() OVERRIDE {
266 glBindTexture(GL_TEXTURE_2D, texture_id());
267 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
268 size().width(), size().height(), 0,
269 GL_RGBA, GL_UNSIGNED_BYTE, shared_mem_->memory());
270 glFlush();
271 }
272
273 virtual TransportDIB::Handle Handle() const OVERRIDE {
274 return shared_mem_->handle();
275 }
276
277 protected:
278 virtual ~ImageTransportClientOSMesa() {
279 unsigned int texture = texture_id();
280 if (texture) {
281 scoped_ptr<gfx::ScopedMakeCurrent> bind(
282 factory_->GetScopedMakeCurrent());
283 glDeleteTextures(1, &texture);
284 glFlush();
285 }
286 }
287
288 private:
289 ImageTransportFactory* factory_;
290 scoped_ptr<TransportDIB> shared_mem_;
291 static uint32 next_handle_;
292 };
293 uint32 ImageTransportClientOSMesa::next_handle_ = 0;
294
295 } // anonymous namespace
296
297 ImageTransportClient* ImageTransportClient::Create(
298 ImageTransportFactory* factory,
299 const gfx::Size& size) {
300 switch (gfx::GetGLImplementation()) {
301 case gfx::kGLImplementationOSMesaGL:
302 return new ImageTransportClientOSMesa(factory, size);
303 case gfx::kGLImplementationDesktopGL:
304 return new ImageTransportClientGLX(factory, size);
305 case gfx::kGLImplementationEGLGLES2:
306 return new ImageTransportClientEGL(factory, size);
307 default:
308 NOTREACHED();
309 return NULL;
310 }
311 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698