- add sources.
[platform/framework/web/crosswalk.git] / src / ui / gl / gl_surface_x11.cc
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/message_loop.h"
11 #include "third_party/mesa/src/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   gfx::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   gfx::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     gfx::AcceleratedWidget window) {
270   TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface");
271   switch (GetGLImplementation()) {
272     case kGLImplementationOSMesaGL: {
273       scoped_refptr<GLSurface> surface(
274           new NativeViewGLSurfaceOSMesa(window));
275       if (!surface->Initialize())
276         return NULL;
277
278       return surface;
279     }
280     case kGLImplementationDesktopGL: {
281       scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX(window));
282       if (!surface->Initialize())
283         return NULL;
284
285       return surface;
286     }
287     case kGLImplementationEGLGLES2: {
288       scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(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     const gfx::Size& size) {
304   TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface");
305   switch (GetGLImplementation()) {
306     case kGLImplementationOSMesaGL: {
307       scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
308                                                            size));
309       if (!surface->Initialize())
310         return NULL;
311
312       return surface;
313     }
314     case kGLImplementationDesktopGL: {
315       scoped_refptr<GLSurface> surface(new PbufferGLSurfaceGLX(size));
316       if (!surface->Initialize())
317         return NULL;
318
319       return surface;
320     }
321     case kGLImplementationEGLGLES2: {
322       scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(size));
323       if (!surface->Initialize())
324         return NULL;
325
326       return surface;
327     }
328     case kGLImplementationMockGL:
329       return new GLSurfaceStub;
330     default:
331       NOTREACHED();
332       return NULL;
333   }
334 }
335
336 }  // namespace gfx