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