NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / ui / gl / gl_surface_x11.cc
blob3673a1de592c98cf5787823999435358758d1de8
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.
5 #include "ui/gl/gl_surface.h"
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"
19 namespace gfx {
21 namespace {
22 Display* g_osmesa_display;
23 } // namespace
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);
31 static bool InitializeOneOff();
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;
42 protected:
43 virtual ~NativeViewGLSurfaceOSMesa();
45 private:
46 GC window_graphics_context_;
47 gfx::AcceleratedWidget window_;
48 GC pixmap_graphics_context_;
49 Pixmap pixmap_;
51 DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa);
54 bool GLSurface::InitializeOneOffInternal() {
55 switch (GetGLImplementation()) {
56 case kGLImplementationDesktopGL:
57 if (!GLSurfaceGLX::InitializeOneOff()) {
58 LOG(ERROR) << "GLSurfaceGLX::InitializeOneOff failed.";
59 return false;
61 break;
62 case kGLImplementationOSMesaGL:
63 if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) {
64 LOG(ERROR) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed.";
65 return false;
67 break;
68 case kGLImplementationEGLGLES2:
69 if (!GLSurfaceEGL::InitializeOneOff()) {
70 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
71 return false;
73 break;
74 default:
75 break;
78 return true;
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);
91 bool NativeViewGLSurfaceOSMesa::InitializeOneOff() {
92 static bool initialized = false;
93 if (initialized)
94 return true;
96 g_osmesa_display = base::MessagePumpForUI::GetDefaultXDisplay();
97 if (!g_osmesa_display) {
98 LOG(ERROR) << "XOpenDisplay failed.";
99 return false;
102 initialized = true;
103 return true;
106 bool NativeViewGLSurfaceOSMesa::Initialize() {
107 if (!GLSurfaceOSMesa::Initialize())
108 return false;
110 window_graphics_context_ = XCreateGC(g_osmesa_display,
111 window_,
113 NULL);
114 if (!window_graphics_context_) {
115 LOG(ERROR) << "XCreateGC failed.";
116 Destroy();
117 return false;
120 return true;
123 void NativeViewGLSurfaceOSMesa::Destroy() {
124 if (pixmap_graphics_context_) {
125 XFreeGC(g_osmesa_display, pixmap_graphics_context_);
126 pixmap_graphics_context_ = NULL;
129 if (pixmap_) {
130 XFreePixmap(g_osmesa_display, pixmap_);
131 pixmap_ = 0;
134 if (window_graphics_context_) {
135 XFreeGC(g_osmesa_display, window_graphics_context_);
136 window_graphics_context_ = NULL;
139 XSync(g_osmesa_display, False);
142 bool NativeViewGLSurfaceOSMesa::Resize(const gfx::Size& new_size) {
143 if (!GLSurfaceOSMesa::Resize(new_size))
144 return false;
146 XWindowAttributes attributes;
147 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
148 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
149 return false;
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;
157 if (pixmap_) {
158 XFreePixmap(g_osmesa_display, pixmap_);
159 pixmap_ = 0;
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;
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;
180 return true;
183 bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
184 return false;
187 bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
188 TRACE_EVENT2("gpu", "NativeViewGLSurfaceOSMesa:RealSwapBuffers",
189 "width", GetSize().width(),
190 "height", GetSize().height());
192 gfx::Size size = GetSize();
194 XWindowAttributes attributes;
195 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
196 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
197 return false;
200 // Copy the frame into the pixmap.
201 gfx::PutARGBImage(g_osmesa_display,
202 attributes.visual,
203 attributes.depth,
204 pixmap_,
205 pixmap_graphics_context_,
206 static_cast<const uint8*>(GetHandle()),
207 size.width(),
208 size.height());
210 // Copy the pixmap to the window.
211 XCopyArea(g_osmesa_display,
212 pixmap_,
213 window_,
214 window_graphics_context_,
215 0, 0,
216 size.width(), size.height(),
217 0, 0);
219 return true;
222 std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
223 std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
224 extensions += extensions.empty() ? "" : " ";
225 extensions += "GL_CHROMIUM_post_sub_buffer";
226 return extensions;
229 bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
230 int x, int y, int width, int height) {
231 gfx::Size size = GetSize();
233 // Move (0,0) from lower-left to upper-left
234 y = size.height() - y - height;
236 XWindowAttributes attributes;
237 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
238 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
239 return false;
242 // Copy the frame into the pixmap.
243 gfx::PutARGBImage(g_osmesa_display,
244 attributes.visual,
245 attributes.depth,
246 pixmap_,
247 pixmap_graphics_context_,
248 static_cast<const uint8*>(GetHandle()),
249 size.width(),
250 size.height(),
251 x, y,
252 x, y,
253 width,
254 height);
256 // Copy the pixmap to the window.
257 XCopyArea(g_osmesa_display,
258 pixmap_,
259 window_,
260 window_graphics_context_,
261 x, y,
262 width, height,
263 x, y);
265 return true;
268 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
269 Destroy();
272 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
273 gfx::AcceleratedWidget window) {
274 TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface");
275 switch (GetGLImplementation()) {
276 case kGLImplementationOSMesaGL: {
277 scoped_refptr<GLSurface> surface(
278 new NativeViewGLSurfaceOSMesa(window));
279 if (!surface->Initialize())
280 return NULL;
282 return surface;
284 case kGLImplementationDesktopGL: {
285 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX(window));
286 if (!surface->Initialize())
287 return NULL;
289 return surface;
291 case kGLImplementationEGLGLES2: {
292 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(window));
293 if (!surface->Initialize())
294 return NULL;
296 return surface;
298 case kGLImplementationMockGL:
299 return new GLSurfaceStub;
300 default:
301 NOTREACHED();
302 return NULL;
306 scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
307 const gfx::Size& size) {
308 TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface");
309 switch (GetGLImplementation()) {
310 case kGLImplementationOSMesaGL: {
311 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
312 size));
313 if (!surface->Initialize())
314 return NULL;
316 return surface;
318 case kGLImplementationDesktopGL: {
319 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceGLX(size));
320 if (!surface->Initialize())
321 return NULL;
323 return surface;
325 case kGLImplementationEGLGLES2: {
326 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(size));
327 if (!surface->Initialize())
328 return NULL;
330 return surface;
332 case kGLImplementationMockGL:
333 return new GLSurfaceStub;
334 default:
335 NOTREACHED();
336 return NULL;
340 } // namespace gfx