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 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_
<< ".";
200 // Copy the frame into the pixmap.
201 gfx::PutARGBImage(g_osmesa_display
,
205 pixmap_graphics_context_
,
206 static_cast<const uint8
*>(GetHandle()),
210 // Copy the pixmap to the window.
211 XCopyArea(g_osmesa_display
,
214 window_graphics_context_
,
216 size
.width(), size
.height(),
222 std::string
NativeViewGLSurfaceOSMesa::GetExtensions() {
223 std::string extensions
= gfx::GLSurfaceOSMesa::GetExtensions();
224 extensions
+= extensions
.empty() ? "" : " ";
225 extensions
+= "GL_CHROMIUM_post_sub_buffer";
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_
<< ".";
242 // Copy the frame into the pixmap.
243 gfx::PutARGBImage(g_osmesa_display
,
247 pixmap_graphics_context_
,
248 static_cast<const uint8
*>(GetHandle()),
256 // Copy the pixmap to the window.
257 XCopyArea(g_osmesa_display
,
260 window_graphics_context_
,
268 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
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())
284 case kGLImplementationDesktopGL
: {
285 scoped_refptr
<GLSurface
> surface(new NativeViewGLSurfaceGLX(window
));
286 if (!surface
->Initialize())
291 case kGLImplementationEGLGLES2
: {
292 scoped_refptr
<GLSurface
> surface(new NativeViewGLSurfaceEGL(window
));
293 if (!surface
->Initialize())
298 case kGLImplementationMockGL
:
299 return new GLSurfaceStub
;
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
,
313 if (!surface
->Initialize())
318 case kGLImplementationDesktopGL
: {
319 scoped_refptr
<GLSurface
> surface(new PbufferGLSurfaceGLX(size
));
320 if (!surface
->Initialize())
325 case kGLImplementationEGLGLES2
: {
326 scoped_refptr
<GLSurface
> surface(new PbufferGLSurfaceEGL(size
));
327 if (!surface
->Initialize())
332 case kGLImplementationMockGL
:
333 return new GLSurfaceStub
;