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 "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 virtual bool Initialize() OVERRIDE;
32 virtual void Destroy() OVERRIDE;
33 virtual bool Resize(const gfx::Size& new_size) OVERRIDE;
34 virtual bool IsOffscreen() OVERRIDE;
35 virtual bool SwapBuffers() OVERRIDE;
36 virtual bool SupportsPostSubBuffer() OVERRIDE;
37 virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
40 virtual ~NativeViewGLSurfaceOSMesa();
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 bool 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_ << ".";
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_,
222 bool NativeViewGLSurfaceOSMesa::SupportsPostSubBuffer() {
226 bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
227 int x, int y, int width, int height) {
228 gfx::Size size = GetSize();
230 // Move (0,0) from lower-left to upper-left
231 y = size.height() - y - height;
233 XWindowAttributes attributes;
234 if (!XGetWindowAttributes(xdisplay_, window_, &attributes)) {
235 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
239 // Copy the frame into the pixmap.
240 gfx::PutARGBImage(xdisplay_,
244 pixmap_graphics_context_,
245 static_cast<const uint8*>(GetHandle()),
255 // Copy the pixmap to the window.
259 window_graphics_context_,
270 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
274 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
275 gfx::AcceleratedWidget window) {
276 TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface");
277 switch (GetGLImplementation()) {
278 case kGLImplementationOSMesaGL: {
279 scoped_refptr<GLSurface> surface(
280 new NativeViewGLSurfaceOSMesa(window));
281 if (!surface->Initialize())
286 case kGLImplementationDesktopGL: {
287 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX(window));
288 if (!surface->Initialize())
293 case kGLImplementationEGLGLES2: {
294 DCHECK(window != gfx::kNullAcceleratedWidget);
295 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(window));
296 if (!surface->Initialize())
301 case kGLImplementationMockGL:
302 return new GLSurfaceStub;
309 scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
310 const gfx::Size& size) {
311 TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface");
312 switch (GetGLImplementation()) {
313 case kGLImplementationOSMesaGL: {
314 scoped_refptr<GLSurface> surface(
315 new GLSurfaceOSMesa(OSMesaSurfaceFormatRGBA, size));
316 if (!surface->Initialize())
321 case kGLImplementationDesktopGL: {
322 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceGLX(size));
323 if (!surface->Initialize())
328 case kGLImplementationEGLGLES2: {
329 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(size));
330 if (!surface->Initialize())
335 case kGLImplementationMockGL:
336 return new GLSurfaceStub;
343 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
344 return gfx::GetXDisplay();