Roll src/third_party/WebKit f56547f:01e6b5d (svn 199576:199577)
[chromium-blink-merge.git] / ui / gl / gl_surface_x11.cc
blob4e14a43b4d12f851b7b9497192d019d334d2839e
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/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/trace_event/trace_event.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"
20 namespace gfx {
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);
28 static bool InitializeOneOff();
30 // Implement a subset of GLSurface.
31 bool Initialize() override;
32 void Destroy() override;
33 bool Resize(const gfx::Size& new_size) override;
34 bool IsOffscreen() override;
35 gfx::SwapResult SwapBuffers() override;
36 bool SupportsPostSubBuffer() override;
37 gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
39 protected:
40 ~NativeViewGLSurfaceOSMesa() override;
42 private:
43 Display* xdisplay_;
44 GC window_graphics_context_;
45 gfx::AcceleratedWidget window_;
46 GC pixmap_graphics_context_;
47 Pixmap pixmap_;
49 DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa);
52 bool GLSurface::InitializeOneOffInternal() {
53 switch (GetGLImplementation()) {
54 case kGLImplementationDesktopGL:
55 if (!GLSurfaceGLX::InitializeOneOff()) {
56 LOG(ERROR) << "GLSurfaceGLX::InitializeOneOff failed.";
57 return false;
59 break;
60 case kGLImplementationOSMesaGL:
61 if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) {
62 LOG(ERROR) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed.";
63 return false;
65 break;
66 case kGLImplementationEGLGLES2:
67 if (!GLSurfaceEGL::InitializeOneOff()) {
68 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
69 return false;
71 break;
72 default:
73 break;
76 return true;
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_);
91 // static
92 bool NativeViewGLSurfaceOSMesa::InitializeOneOff() {
93 static bool initialized = false;
94 if (initialized)
95 return true;
97 if (!gfx::GetXDisplay()) {
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(xdisplay_, window_, 0, NULL);
111 if (!window_graphics_context_) {
112 LOG(ERROR) << "XCreateGC failed.";
113 Destroy();
114 return false;
117 return true;
120 void NativeViewGLSurfaceOSMesa::Destroy() {
121 if (pixmap_graphics_context_) {
122 XFreeGC(xdisplay_, pixmap_graphics_context_);
123 pixmap_graphics_context_ = NULL;
126 if (pixmap_) {
127 XFreePixmap(xdisplay_, pixmap_);
128 pixmap_ = 0;
131 if (window_graphics_context_) {
132 XFreeGC(xdisplay_, window_graphics_context_);
133 window_graphics_context_ = NULL;
136 XSync(xdisplay_, False);
139 bool NativeViewGLSurfaceOSMesa::Resize(const gfx::Size& new_size) {
140 if (!GLSurfaceOSMesa::Resize(new_size))
141 return false;
143 XWindowAttributes attributes;
144 if (!XGetWindowAttributes(xdisplay_, window_, &attributes)) {
145 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
146 return false;
149 // Destroy the previous pixmap and graphics context.
150 if (pixmap_graphics_context_) {
151 XFreeGC(xdisplay_, pixmap_graphics_context_);
152 pixmap_graphics_context_ = NULL;
154 if (pixmap_) {
155 XFreePixmap(xdisplay_, pixmap_);
156 pixmap_ = 0;
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;
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;
177 return true;
180 bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
181 return false;
184 gfx::SwapResult NativeViewGLSurfaceOSMesa::SwapBuffers() {
185 TRACE_EVENT2("gpu", "NativeViewGLSurfaceOSMesa:RealSwapBuffers",
186 "width", GetSize().width(),
187 "height", GetSize().height());
189 gfx::Size size = GetSize();
191 XWindowAttributes attributes;
192 if (!XGetWindowAttributes(xdisplay_, window_, &attributes)) {
193 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
194 return gfx::SwapResult::SWAP_FAILED;
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());
207 // Copy the pixmap to the window.
208 XCopyArea(xdisplay_,
209 pixmap_,
210 window_,
211 window_graphics_context_,
214 size.width(),
215 size.height(),
219 return gfx::SwapResult::SWAP_ACK;
222 bool NativeViewGLSurfaceOSMesa::SupportsPostSubBuffer() {
223 return true;
226 gfx::SwapResult NativeViewGLSurfaceOSMesa::PostSubBuffer(int x,
227 int y,
228 int width,
229 int height) {
230 gfx::Size size = GetSize();
232 // Move (0,0) from lower-left to upper-left
233 y = size.height() - y - height;
235 XWindowAttributes attributes;
236 if (!XGetWindowAttributes(xdisplay_, window_, &attributes)) {
237 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
238 return gfx::SwapResult::SWAP_FAILED;
241 // Copy the frame into the pixmap.
242 gfx::PutARGBImage(xdisplay_,
243 attributes.visual,
244 attributes.depth,
245 pixmap_,
246 pixmap_graphics_context_,
247 static_cast<const uint8*>(GetHandle()),
248 size.width(),
249 size.height(),
254 width,
255 height);
257 // Copy the pixmap to the window.
258 XCopyArea(xdisplay_,
259 pixmap_,
260 window_,
261 window_graphics_context_,
264 width,
265 height,
269 return gfx::SwapResult::SWAP_ACK;
272 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
273 Destroy();
276 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
277 gfx::AcceleratedWidget window) {
278 TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface");
279 switch (GetGLImplementation()) {
280 case kGLImplementationOSMesaGL: {
281 scoped_refptr<GLSurface> surface(
282 new NativeViewGLSurfaceOSMesa(window));
283 if (!surface->Initialize())
284 return NULL;
286 return surface;
288 case kGLImplementationDesktopGL: {
289 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX(window));
290 if (!surface->Initialize())
291 return NULL;
293 return surface;
295 case kGLImplementationEGLGLES2: {
296 DCHECK(window != gfx::kNullAcceleratedWidget);
297 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(window));
298 if (!surface->Initialize())
299 return NULL;
301 return surface;
303 case kGLImplementationMockGL:
304 return new GLSurfaceStub;
305 default:
306 NOTREACHED();
307 return NULL;
311 scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
312 const gfx::Size& size) {
313 TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface");
314 switch (GetGLImplementation()) {
315 case kGLImplementationOSMesaGL: {
316 scoped_refptr<GLSurface> surface(
317 new GLSurfaceOSMesa(OSMesaSurfaceFormatRGBA, size));
318 if (!surface->Initialize())
319 return NULL;
321 return surface;
323 case kGLImplementationDesktopGL: {
324 scoped_refptr<GLSurface> surface(
325 new UnmappedNativeViewGLSurfaceGLX(size));
326 if (!surface->Initialize())
327 return NULL;
329 return surface;
331 case kGLImplementationEGLGLES2: {
332 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(size));
333 if (!surface->Initialize())
334 return NULL;
336 return surface;
338 case kGLImplementationMockGL:
339 return new GLSurfaceStub;
340 default:
341 NOTREACHED();
342 return NULL;
346 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
347 return gfx::GetXDisplay();
350 } // namespace gfx