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"
22 // This OSMesa GL surface can use XLib to swap the contents of the buffer to a
24 class NativeViewGLSurfaceOSMesa
: public GLSurfaceOSMesa
{
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
;
40 ~NativeViewGLSurfaceOSMesa() override
;
44 GC window_graphics_context_
;
45 gfx::AcceleratedWidget window_
;
46 GC pixmap_graphics_context_
;
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.";
60 case kGLImplementationOSMesaGL
:
61 if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) {
62 LOG(ERROR
) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed.";
66 case kGLImplementationEGLGLES2
:
67 if (!GLSurfaceEGL::InitializeOneOff()) {
68 LOG(ERROR
) << "GLSurfaceEGL::InitializeOneOff failed.";
79 NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
80 gfx::AcceleratedWidget window
)
81 : GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA
, gfx::Size(1, 1)),
82 xdisplay_(gfx::GetXDisplay()),
83 window_graphics_context_(0),
85 pixmap_graphics_context_(0),
92 bool NativeViewGLSurfaceOSMesa::InitializeOneOff() {
93 static bool initialized
= false;
97 if (!gfx::GetXDisplay()) {
98 LOG(ERROR
) << "XOpenDisplay failed.";
106 bool NativeViewGLSurfaceOSMesa::Initialize() {
107 if (!GLSurfaceOSMesa::Initialize())
110 window_graphics_context_
= XCreateGC(xdisplay_
, window_
, 0, NULL
);
111 if (!window_graphics_context_
) {
112 LOG(ERROR
) << "XCreateGC failed.";
120 void NativeViewGLSurfaceOSMesa::Destroy() {
121 if (pixmap_graphics_context_
) {
122 XFreeGC(xdisplay_
, pixmap_graphics_context_
);
123 pixmap_graphics_context_
= NULL
;
127 XFreePixmap(xdisplay_
, pixmap_
);
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
))
143 XWindowAttributes attributes
;
144 if (!XGetWindowAttributes(xdisplay_
, window_
, &attributes
)) {
145 LOG(ERROR
) << "XGetWindowAttributes failed for window " << window_
<< ".";
149 // Destroy the previous pixmap and graphics context.
150 if (pixmap_graphics_context_
) {
151 XFreeGC(xdisplay_
, pixmap_graphics_context_
);
152 pixmap_graphics_context_
= NULL
;
155 XFreePixmap(xdisplay_
, pixmap_
);
159 // Recreate a pixmap to hold the frame.
160 pixmap_
= XCreatePixmap(xdisplay_
,
166 LOG(ERROR
) << "XCreatePixmap failed.";
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";
180 bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
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_
,
202 pixmap_graphics_context_
,
203 static_cast<const uint8
*>(GetHandle()),
207 // Copy the pixmap to the window.
211 window_graphics_context_
,
219 return gfx::SwapResult::SWAP_ACK
;
222 bool NativeViewGLSurfaceOSMesa::SupportsPostSubBuffer() {
226 gfx::SwapResult
NativeViewGLSurfaceOSMesa::PostSubBuffer(int x
,
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_
,
246 pixmap_graphics_context_
,
247 static_cast<const uint8
*>(GetHandle()),
257 // Copy the pixmap to the window.
261 window_graphics_context_
,
269 return gfx::SwapResult::SWAP_ACK
;
272 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
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())
288 case kGLImplementationDesktopGL
: {
289 scoped_refptr
<GLSurface
> surface(new NativeViewGLSurfaceGLX(window
));
290 if (!surface
->Initialize())
295 case kGLImplementationEGLGLES2
: {
296 DCHECK(window
!= gfx::kNullAcceleratedWidget
);
297 scoped_refptr
<GLSurface
> surface(new NativeViewGLSurfaceEGL(window
));
298 if (!surface
->Initialize())
303 case kGLImplementationMockGL
:
304 return new GLSurfaceStub
;
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())
323 case kGLImplementationDesktopGL
: {
324 scoped_refptr
<GLSurface
> surface(
325 new UnmappedNativeViewGLSurfaceGLX(size
));
326 if (!surface
->Initialize())
331 case kGLImplementationEGLGLES2
: {
332 scoped_refptr
<GLSurface
> surface(new PbufferGLSurfaceEGL(size
));
333 if (!surface
->Initialize())
338 case kGLImplementationMockGL
:
339 return new GLSurfaceStub
;
346 EGLNativeDisplayType
GetPlatformDefaultEGLNativeDisplay() {
347 return gfx::GetXDisplay();