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/gfx/native_widget_types.h"
13 #include "ui/gfx/x/x11_types.h"
14 #include "ui/gl/gl_bindings.h"
15 #include "ui/gl/gl_implementation.h"
16 #include "ui/gl/gl_surface_egl.h"
17 #include "ui/gl/gl_surface_glx.h"
18 #include "ui/gl/gl_surface_osmesa.h"
19 #include "ui/gl/gl_surface_stub.h"
23 // This OSMesa GL surface can use XLib to swap the contents of the buffer to a
25 class NativeViewGLSurfaceOSMesa
: public GLSurfaceOSMesa
{
27 explicit NativeViewGLSurfaceOSMesa(gfx::AcceleratedWidget window
);
29 static bool InitializeOneOff();
31 // Implement a subset of GLSurface.
32 virtual bool Initialize() OVERRIDE
;
33 virtual void Destroy() OVERRIDE
;
34 virtual bool Resize(const gfx::Size
& new_size
) OVERRIDE
;
35 virtual bool IsOffscreen() OVERRIDE
;
36 virtual bool SwapBuffers() OVERRIDE
;
37 virtual bool SupportsPostSubBuffer() OVERRIDE
;
38 virtual bool PostSubBuffer(int x
, int y
, int width
, int height
) OVERRIDE
;
41 virtual ~NativeViewGLSurfaceOSMesa();
45 GC window_graphics_context_
;
46 gfx::AcceleratedWidget window_
;
47 GC pixmap_graphics_context_
;
50 DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa
);
53 bool GLSurface::InitializeOneOffInternal() {
54 switch (GetGLImplementation()) {
55 case kGLImplementationDesktopGL
:
56 if (!GLSurfaceGLX::InitializeOneOff()) {
57 LOG(ERROR
) << "GLSurfaceGLX::InitializeOneOff failed.";
61 case kGLImplementationOSMesaGL
:
62 if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) {
63 LOG(ERROR
) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed.";
67 case kGLImplementationEGLGLES2
:
68 if (!GLSurfaceEGL::InitializeOneOff()) {
69 LOG(ERROR
) << "GLSurfaceEGL::InitializeOneOff failed.";
80 NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
81 gfx::AcceleratedWidget window
)
82 : GLSurfaceOSMesa(OSMESA_BGRA
, gfx::Size(1, 1)),
83 xdisplay_(gfx::GetXDisplay()),
84 window_graphics_context_(0),
86 pixmap_graphics_context_(0),
93 bool NativeViewGLSurfaceOSMesa::InitializeOneOff() {
94 static bool initialized
= false;
98 if (!gfx::GetXDisplay()) {
99 LOG(ERROR
) << "XOpenDisplay failed.";
107 bool NativeViewGLSurfaceOSMesa::Initialize() {
108 if (!GLSurfaceOSMesa::Initialize())
111 window_graphics_context_
= XCreateGC(xdisplay_
, window_
, 0, NULL
);
112 if (!window_graphics_context_
) {
113 LOG(ERROR
) << "XCreateGC failed.";
121 void NativeViewGLSurfaceOSMesa::Destroy() {
122 if (pixmap_graphics_context_
) {
123 XFreeGC(xdisplay_
, pixmap_graphics_context_
);
124 pixmap_graphics_context_
= NULL
;
128 XFreePixmap(xdisplay_
, pixmap_
);
132 if (window_graphics_context_
) {
133 XFreeGC(xdisplay_
, window_graphics_context_
);
134 window_graphics_context_
= NULL
;
137 XSync(xdisplay_
, False
);
140 bool NativeViewGLSurfaceOSMesa::Resize(const gfx::Size
& new_size
) {
141 if (!GLSurfaceOSMesa::Resize(new_size
))
144 XWindowAttributes attributes
;
145 if (!XGetWindowAttributes(xdisplay_
, window_
, &attributes
)) {
146 LOG(ERROR
) << "XGetWindowAttributes failed for window " << window_
<< ".";
150 // Destroy the previous pixmap and graphics context.
151 if (pixmap_graphics_context_
) {
152 XFreeGC(xdisplay_
, pixmap_graphics_context_
);
153 pixmap_graphics_context_
= NULL
;
156 XFreePixmap(xdisplay_
, pixmap_
);
160 // Recreate a pixmap to hold the frame.
161 pixmap_
= XCreatePixmap(xdisplay_
,
167 LOG(ERROR
) << "XCreatePixmap failed.";
171 // Recreate a graphics context for the pixmap.
172 pixmap_graphics_context_
= XCreateGC(xdisplay_
, pixmap_
, 0, NULL
);
173 if (!pixmap_graphics_context_
) {
174 LOG(ERROR
) << "XCreateGC failed";
181 bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
185 bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
186 TRACE_EVENT2("gpu", "NativeViewGLSurfaceOSMesa:RealSwapBuffers",
187 "width", GetSize().width(),
188 "height", GetSize().height());
190 gfx::Size size
= GetSize();
192 XWindowAttributes attributes
;
193 if (!XGetWindowAttributes(xdisplay_
, window_
, &attributes
)) {
194 LOG(ERROR
) << "XGetWindowAttributes failed for window " << window_
<< ".";
198 // Copy the frame into the pixmap.
199 gfx::PutARGBImage(xdisplay_
,
203 pixmap_graphics_context_
,
204 static_cast<const uint8
*>(GetHandle()),
208 // Copy the pixmap to the window.
212 window_graphics_context_
,
223 bool NativeViewGLSurfaceOSMesa::SupportsPostSubBuffer() {
227 bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
228 int x
, int y
, int width
, int height
) {
229 gfx::Size size
= GetSize();
231 // Move (0,0) from lower-left to upper-left
232 y
= size
.height() - y
- height
;
234 XWindowAttributes attributes
;
235 if (!XGetWindowAttributes(xdisplay_
, window_
, &attributes
)) {
236 LOG(ERROR
) << "XGetWindowAttributes failed for window " << window_
<< ".";
240 // Copy the frame into the pixmap.
241 gfx::PutARGBImage(xdisplay_
,
245 pixmap_graphics_context_
,
246 static_cast<const uint8
*>(GetHandle()),
256 // Copy the pixmap to the window.
260 window_graphics_context_
,
271 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
275 scoped_refptr
<GLSurface
> GLSurface::CreateViewGLSurface(
276 gfx::AcceleratedWidget window
) {
277 TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface");
278 switch (GetGLImplementation()) {
279 case kGLImplementationOSMesaGL
: {
280 scoped_refptr
<GLSurface
> surface(
281 new NativeViewGLSurfaceOSMesa(window
));
282 if (!surface
->Initialize())
287 case kGLImplementationDesktopGL
: {
288 scoped_refptr
<GLSurface
> surface(new NativeViewGLSurfaceGLX(window
));
289 if (!surface
->Initialize())
294 case kGLImplementationEGLGLES2
: {
295 DCHECK(window
!= gfx::kNullAcceleratedWidget
);
296 scoped_refptr
<GLSurface
> surface(new NativeViewGLSurfaceEGL(window
));
297 if (!surface
->Initialize())
302 case kGLImplementationMockGL
:
303 return new GLSurfaceStub
;
310 scoped_refptr
<GLSurface
> GLSurface::CreateOffscreenGLSurface(
311 const gfx::Size
& size
) {
312 TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface");
313 switch (GetGLImplementation()) {
314 case kGLImplementationOSMesaGL
: {
315 scoped_refptr
<GLSurface
> surface(new GLSurfaceOSMesa(OSMESA_RGBA
,
317 if (!surface
->Initialize())
322 case kGLImplementationDesktopGL
: {
323 scoped_refptr
<GLSurface
> surface(new PbufferGLSurfaceGLX(size
));
324 if (!surface
->Initialize())
329 case kGLImplementationEGLGLES2
: {
330 scoped_refptr
<GLSurface
> surface(new PbufferGLSurfaceEGL(size
));
331 if (!surface
->Initialize())
336 case kGLImplementationMockGL
:
337 return new GLSurfaceStub
;
344 EGLNativeDisplayType
GetPlatformDefaultEGLNativeDisplay() {
345 return gfx::GetXDisplay();