OLD | NEW |
| (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 "ui/gl/gl_surface.h" | |
6 | |
7 #include "base/debug/trace_event.h" | |
8 #include "base/logging.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/message_loop.h" | |
11 #include "third_party/mesa/MesaLib/include/GL/osmesa.h" | |
12 #include "ui/gl/gl_bindings.h" | |
13 #include "ui/gl/gl_implementation.h" | |
14 #include "ui/gl/gl_surface_egl.h" | |
15 #include "ui/gl/gl_surface_glx.h" | |
16 #include "ui/gl/gl_surface_osmesa.h" | |
17 #include "ui/gl/gl_surface_stub.h" | |
18 | |
19 namespace gfx { | |
20 | |
21 namespace { | |
22 Display* g_osmesa_display; | |
23 } // namespace | |
24 | |
25 // This OSMesa GL surface can use XLib to swap the contents of the buffer to a | |
26 // view. | |
27 class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa { | |
28 public: | |
29 explicit NativeViewGLSurfaceOSMesa(gfx::AcceleratedWidget window); | |
30 | |
31 static bool InitializeOneOff(); | |
32 | |
33 // Implement a subset of GLSurface. | |
34 virtual bool Initialize() OVERRIDE; | |
35 virtual void Destroy() OVERRIDE; | |
36 virtual bool Resize(const gfx::Size& new_size) OVERRIDE; | |
37 virtual bool IsOffscreen() OVERRIDE; | |
38 virtual bool SwapBuffers() OVERRIDE; | |
39 virtual std::string GetExtensions() OVERRIDE; | |
40 virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE; | |
41 | |
42 protected: | |
43 virtual ~NativeViewGLSurfaceOSMesa(); | |
44 | |
45 private: | |
46 GC window_graphics_context_; | |
47 gfx::AcceleratedWidget window_; | |
48 GC pixmap_graphics_context_; | |
49 Pixmap pixmap_; | |
50 | |
51 DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa); | |
52 }; | |
53 | |
54 bool GLSurface::InitializeOneOffInternal() { | |
55 switch (GetGLImplementation()) { | |
56 case kGLImplementationDesktopGL: | |
57 if (!GLSurfaceGLX::InitializeOneOff()) { | |
58 LOG(ERROR) << "GLSurfaceGLX::InitializeOneOff failed."; | |
59 return false; | |
60 } | |
61 break; | |
62 case kGLImplementationOSMesaGL: | |
63 if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) { | |
64 LOG(ERROR) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed."; | |
65 return false; | |
66 } | |
67 break; | |
68 case kGLImplementationEGLGLES2: | |
69 if (!GLSurfaceEGL::InitializeOneOff()) { | |
70 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed."; | |
71 return false; | |
72 } | |
73 break; | |
74 default: | |
75 break; | |
76 } | |
77 | |
78 return true; | |
79 } | |
80 | |
81 NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa( | |
82 gfx::AcceleratedWidget window) | |
83 : GLSurfaceOSMesa(OSMESA_BGRA, gfx::Size(1, 1)), | |
84 window_graphics_context_(0), | |
85 window_(window), | |
86 pixmap_graphics_context_(0), | |
87 pixmap_(0) { | |
88 DCHECK(window); | |
89 } | |
90 | |
91 bool NativeViewGLSurfaceOSMesa::InitializeOneOff() { | |
92 static bool initialized = false; | |
93 if (initialized) | |
94 return true; | |
95 | |
96 g_osmesa_display = base::MessagePumpForUI::GetDefaultXDisplay(); | |
97 if (!g_osmesa_display) { | |
98 LOG(ERROR) << "XOpenDisplay failed."; | |
99 return false; | |
100 } | |
101 | |
102 initialized = true; | |
103 return true; | |
104 } | |
105 | |
106 bool NativeViewGLSurfaceOSMesa::Initialize() { | |
107 if (!GLSurfaceOSMesa::Initialize()) | |
108 return false; | |
109 | |
110 window_graphics_context_ = XCreateGC(g_osmesa_display, | |
111 window_, | |
112 0, | |
113 NULL); | |
114 if (!window_graphics_context_) { | |
115 LOG(ERROR) << "XCreateGC failed."; | |
116 Destroy(); | |
117 return false; | |
118 } | |
119 | |
120 return true; | |
121 } | |
122 | |
123 void NativeViewGLSurfaceOSMesa::Destroy() { | |
124 if (pixmap_graphics_context_) { | |
125 XFreeGC(g_osmesa_display, pixmap_graphics_context_); | |
126 pixmap_graphics_context_ = NULL; | |
127 } | |
128 | |
129 if (pixmap_) { | |
130 XFreePixmap(g_osmesa_display, pixmap_); | |
131 pixmap_ = 0; | |
132 } | |
133 | |
134 if (window_graphics_context_) { | |
135 XFreeGC(g_osmesa_display, window_graphics_context_); | |
136 window_graphics_context_ = NULL; | |
137 } | |
138 | |
139 XSync(g_osmesa_display, False); | |
140 } | |
141 | |
142 bool NativeViewGLSurfaceOSMesa::Resize(const gfx::Size& new_size) { | |
143 if (!GLSurfaceOSMesa::Resize(new_size)) | |
144 return false; | |
145 | |
146 XWindowAttributes attributes; | |
147 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) { | |
148 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; | |
149 return false; | |
150 } | |
151 | |
152 // Destroy the previous pixmap and graphics context. | |
153 if (pixmap_graphics_context_) { | |
154 XFreeGC(g_osmesa_display, pixmap_graphics_context_); | |
155 pixmap_graphics_context_ = NULL; | |
156 } | |
157 if (pixmap_) { | |
158 XFreePixmap(g_osmesa_display, pixmap_); | |
159 pixmap_ = 0; | |
160 } | |
161 | |
162 // Recreate a pixmap to hold the frame. | |
163 pixmap_ = XCreatePixmap(g_osmesa_display, | |
164 window_, | |
165 new_size.width(), | |
166 new_size.height(), | |
167 attributes.depth); | |
168 if (!pixmap_) { | |
169 LOG(ERROR) << "XCreatePixmap failed."; | |
170 return false; | |
171 } | |
172 | |
173 // Recreate a graphics context for the pixmap. | |
174 pixmap_graphics_context_ = XCreateGC(g_osmesa_display, pixmap_, 0, NULL); | |
175 if (!pixmap_graphics_context_) { | |
176 LOG(ERROR) << "XCreateGC failed"; | |
177 return false; | |
178 } | |
179 | |
180 return true; | |
181 } | |
182 | |
183 bool NativeViewGLSurfaceOSMesa::IsOffscreen() { | |
184 return false; | |
185 } | |
186 | |
187 bool NativeViewGLSurfaceOSMesa::SwapBuffers() { | |
188 gfx::Size size = GetSize(); | |
189 | |
190 XWindowAttributes attributes; | |
191 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) { | |
192 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; | |
193 return false; | |
194 } | |
195 | |
196 // Copy the frame into the pixmap. | |
197 ui::PutARGBImage(g_osmesa_display, | |
198 attributes.visual, | |
199 attributes.depth, | |
200 pixmap_, | |
201 pixmap_graphics_context_, | |
202 static_cast<const uint8*>(GetHandle()), | |
203 size.width(), | |
204 size.height()); | |
205 | |
206 // Copy the pixmap to the window. | |
207 XCopyArea(g_osmesa_display, | |
208 pixmap_, | |
209 window_, | |
210 window_graphics_context_, | |
211 0, 0, | |
212 size.width(), size.height(), | |
213 0, 0); | |
214 | |
215 return true; | |
216 } | |
217 | |
218 std::string NativeViewGLSurfaceOSMesa::GetExtensions() { | |
219 std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions(); | |
220 extensions += extensions.empty() ? "" : " "; | |
221 extensions += "GL_CHROMIUM_post_sub_buffer"; | |
222 return extensions; | |
223 } | |
224 | |
225 bool NativeViewGLSurfaceOSMesa::PostSubBuffer( | |
226 int x, int y, int width, int height) { | |
227 gfx::Size size = GetSize(); | |
228 | |
229 // Move (0,0) from lower-left to upper-left | |
230 y = size.height() - y - height; | |
231 | |
232 XWindowAttributes attributes; | |
233 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) { | |
234 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; | |
235 return false; | |
236 } | |
237 | |
238 // Copy the frame into the pixmap. | |
239 ui::PutARGBImage(g_osmesa_display, | |
240 attributes.visual, | |
241 attributes.depth, | |
242 pixmap_, | |
243 pixmap_graphics_context_, | |
244 static_cast<const uint8*>(GetHandle()), | |
245 size.width(), | |
246 size.height(), | |
247 x, y, | |
248 x, y, | |
249 width, | |
250 height); | |
251 | |
252 // Copy the pixmap to the window. | |
253 XCopyArea(g_osmesa_display, | |
254 pixmap_, | |
255 window_, | |
256 window_graphics_context_, | |
257 x, y, | |
258 width, height, | |
259 x, y); | |
260 | |
261 return true; | |
262 } | |
263 | |
264 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() { | |
265 Destroy(); | |
266 } | |
267 | |
268 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( | |
269 bool software, | |
270 gfx::AcceleratedWidget window) { | |
271 TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface"); | |
272 if (software) | |
273 return NULL; | |
274 | |
275 switch (GetGLImplementation()) { | |
276 case kGLImplementationOSMesaGL: { | |
277 scoped_refptr<GLSurface> surface( | |
278 new NativeViewGLSurfaceOSMesa(window)); | |
279 if (!surface->Initialize()) | |
280 return NULL; | |
281 | |
282 return surface; | |
283 } | |
284 case kGLImplementationDesktopGL: { | |
285 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX( | |
286 window)); | |
287 if (!surface->Initialize()) | |
288 return NULL; | |
289 | |
290 return surface; | |
291 } | |
292 case kGLImplementationEGLGLES2: { | |
293 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL( | |
294 false, window)); | |
295 if (!surface->Initialize()) | |
296 return NULL; | |
297 | |
298 return surface; | |
299 } | |
300 case kGLImplementationMockGL: | |
301 return new GLSurfaceStub; | |
302 default: | |
303 NOTREACHED(); | |
304 return NULL; | |
305 } | |
306 } | |
307 | |
308 scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface( | |
309 bool software, | |
310 const gfx::Size& size) { | |
311 TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface"); | |
312 if (software) | |
313 return NULL; | |
314 | |
315 switch (GetGLImplementation()) { | |
316 case kGLImplementationOSMesaGL: { | |
317 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA, | |
318 size)); | |
319 if (!surface->Initialize()) | |
320 return NULL; | |
321 | |
322 return surface; | |
323 } | |
324 case kGLImplementationDesktopGL: { | |
325 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceGLX(size)); | |
326 if (!surface->Initialize()) | |
327 return NULL; | |
328 | |
329 return surface; | |
330 } | |
331 case kGLImplementationEGLGLES2: { | |
332 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(false, size)); | |
333 if (!surface->Initialize()) | |
334 return NULL; | |
335 | |
336 return surface; | |
337 } | |
338 case kGLImplementationMockGL: | |
339 return new GLSurfaceStub; | |
340 default: | |
341 NOTREACHED(); | |
342 return NULL; | |
343 } | |
344 } | |
345 | |
346 } // namespace gfx | |
OLD | NEW |