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"
22 Display* g_osmesa_display;
25 // This OSMesa GL surface can use XLib to swap the contents of the buffer to a
27 class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
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;
43 virtual ~NativeViewGLSurfaceOSMesa();
46 GC window_graphics_context_;
47 gfx::AcceleratedWidget window_;
48 GC pixmap_graphics_context_;
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.";
62 case kGLImplementationOSMesaGL:
63 if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) {
64 LOG(ERROR) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed.";
68 case kGLImplementationEGLGLES2:
69 if (!GLSurfaceEGL::InitializeOneOff()) {
70 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
81 NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
82 gfx::AcceleratedWidget window)
83 : GLSurfaceOSMesa(OSMESA_BGRA, gfx::Size(1, 1)),
84 window_graphics_context_(0),
86 pixmap_graphics_context_(0),
91 bool NativeViewGLSurfaceOSMesa::InitializeOneOff() {
92 static bool initialized = false;
96 g_osmesa_display = base::MessagePumpForUI::GetDefaultXDisplay();
97 if (!g_osmesa_display) {
98 LOG(ERROR) << "XOpenDisplay failed.";
106 bool NativeViewGLSurfaceOSMesa::Initialize() {
107 if (!GLSurfaceOSMesa::Initialize())
110 window_graphics_context_ = XCreateGC(g_osmesa_display,
114 if (!window_graphics_context_) {
115 LOG(ERROR) << "XCreateGC failed.";
123 void NativeViewGLSurfaceOSMesa::Destroy() {
124 if (pixmap_graphics_context_) {
125 XFreeGC(g_osmesa_display, pixmap_graphics_context_);
126 pixmap_graphics_context_ = NULL;
130 XFreePixmap(g_osmesa_display, pixmap_);
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))
146 XWindowAttributes attributes;
147 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
148 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
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;
158 XFreePixmap(g_osmesa_display, pixmap_);
162 // Recreate a pixmap to hold the frame.
163 pixmap_ = XCreatePixmap(g_osmesa_display,
169 LOG(ERROR) << "XCreatePixmap failed.";
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";
183 bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
187 bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
188 gfx::Size size = GetSize();
190 XWindowAttributes attributes;
191 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
192 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
196 // Copy the frame into the pixmap.
197 gfx::PutARGBImage(g_osmesa_display,
201 pixmap_graphics_context_,
202 static_cast<const uint8*>(GetHandle()),
206 // Copy the pixmap to the window.
207 XCopyArea(g_osmesa_display,
210 window_graphics_context_,
212 size.width(), size.height(),
218 std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
219 std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
220 extensions += extensions.empty() ? "" : " ";
221 extensions += "GL_CHROMIUM_post_sub_buffer";
225 bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
226 int x, int y, int width, int height) {
227 gfx::Size size = GetSize();
229 // Move (0,0) from lower-left to upper-left
230 y = size.height() - y - height;
232 XWindowAttributes attributes;
233 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
234 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
238 // Copy the frame into the pixmap.
239 gfx::PutARGBImage(g_osmesa_display,
243 pixmap_graphics_context_,
244 static_cast<const uint8*>(GetHandle()),
252 // Copy the pixmap to the window.
253 XCopyArea(g_osmesa_display,
256 window_graphics_context_,
264 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
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())
280 case kGLImplementationDesktopGL: {
281 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX(window));
282 if (!surface->Initialize())
287 case kGLImplementationEGLGLES2: {
288 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(window));
289 if (!surface->Initialize())
294 case kGLImplementationMockGL:
295 return new GLSurfaceStub;
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,
309 if (!surface->Initialize())
314 case kGLImplementationDesktopGL: {
315 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceGLX(size));
316 if (!surface->Initialize())
321 case kGLImplementationEGLGLES2: {
322 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(size));
323 if (!surface->Initialize())
328 case kGLImplementationMockGL:
329 return new GLSurfaceStub;