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