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