| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "ui/gl/gl_surface.h" | |
| 6 | |
| 7 #include "base/debug/trace_event.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/memory/scoped_ptr.h" | |
| 10 #include "base/message_loop.h" | |
| 11 #include "third_party/mesa/MesaLib/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" | |
| 18 | |
| 19 namespace gfx { | |
| 20 | |
| 21 namespace { | |
| 22 Display* g_osmesa_display; | |
| 23 } // namespace | |
| 24 | |
| 25 // This OSMesa GL surface can use XLib to swap the contents of the buffer to a | |
| 26 // view. | |
| 27 class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa { | |
| 28 public: | |
| 29 explicit NativeViewGLSurfaceOSMesa(gfx::AcceleratedWidget window); | |
| 30 | |
| 31 static bool InitializeOneOff(); | |
| 32 | |
| 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; | |
| 41 | |
| 42 protected: | |
| 43 virtual ~NativeViewGLSurfaceOSMesa(); | |
| 44 | |
| 45 private: | |
| 46 GC window_graphics_context_; | |
| 47 gfx::AcceleratedWidget window_; | |
| 48 GC pixmap_graphics_context_; | |
| 49 Pixmap pixmap_; | |
| 50 | |
| 51 DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa); | |
| 52 }; | |
| 53 | |
| 54 bool GLSurface::InitializeOneOffInternal() { | |
| 55 switch (GetGLImplementation()) { | |
| 56 case kGLImplementationDesktopGL: | |
| 57 if (!GLSurfaceGLX::InitializeOneOff()) { | |
| 58 LOG(ERROR) << "GLSurfaceGLX::InitializeOneOff failed."; | |
| 59 return false; | |
| 60 } | |
| 61 break; | |
| 62 case kGLImplementationOSMesaGL: | |
| 63 if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) { | |
| 64 LOG(ERROR) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed."; | |
| 65 return false; | |
| 66 } | |
| 67 break; | |
| 68 case kGLImplementationEGLGLES2: | |
| 69 if (!GLSurfaceEGL::InitializeOneOff()) { | |
| 70 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed."; | |
| 71 return false; | |
| 72 } | |
| 73 break; | |
| 74 default: | |
| 75 break; | |
| 76 } | |
| 77 | |
| 78 return true; | |
| 79 } | |
| 80 | |
| 81 NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa( | |
| 82 gfx::AcceleratedWidget window) | |
| 83 : GLSurfaceOSMesa(OSMESA_BGRA, gfx::Size(1, 1)), | |
| 84 window_graphics_context_(0), | |
| 85 window_(window), | |
| 86 pixmap_graphics_context_(0), | |
| 87 pixmap_(0) { | |
| 88 DCHECK(window); | |
| 89 } | |
| 90 | |
| 91 bool NativeViewGLSurfaceOSMesa::InitializeOneOff() { | |
| 92 static bool initialized = false; | |
| 93 if (initialized) | |
| 94 return true; | |
| 95 | |
| 96 g_osmesa_display = base::MessagePumpForUI::GetDefaultXDisplay(); | |
| 97 if (!g_osmesa_display) { | |
| 98 LOG(ERROR) << "XOpenDisplay failed."; | |
| 99 return false; | |
| 100 } | |
| 101 | |
| 102 initialized = true; | |
| 103 return true; | |
| 104 } | |
| 105 | |
| 106 bool NativeViewGLSurfaceOSMesa::Initialize() { | |
| 107 if (!GLSurfaceOSMesa::Initialize()) | |
| 108 return false; | |
| 109 | |
| 110 window_graphics_context_ = XCreateGC(g_osmesa_display, | |
| 111 window_, | |
| 112 0, | |
| 113 NULL); | |
| 114 if (!window_graphics_context_) { | |
| 115 LOG(ERROR) << "XCreateGC failed."; | |
| 116 Destroy(); | |
| 117 return false; | |
| 118 } | |
| 119 | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 void NativeViewGLSurfaceOSMesa::Destroy() { | |
| 124 if (pixmap_graphics_context_) { | |
| 125 XFreeGC(g_osmesa_display, pixmap_graphics_context_); | |
| 126 pixmap_graphics_context_ = NULL; | |
| 127 } | |
| 128 | |
| 129 if (pixmap_) { | |
| 130 XFreePixmap(g_osmesa_display, pixmap_); | |
| 131 pixmap_ = 0; | |
| 132 } | |
| 133 | |
| 134 if (window_graphics_context_) { | |
| 135 XFreeGC(g_osmesa_display, window_graphics_context_); | |
| 136 window_graphics_context_ = NULL; | |
| 137 } | |
| 138 | |
| 139 XSync(g_osmesa_display, False); | |
| 140 } | |
| 141 | |
| 142 bool NativeViewGLSurfaceOSMesa::Resize(const gfx::Size& new_size) { | |
| 143 if (!GLSurfaceOSMesa::Resize(new_size)) | |
| 144 return false; | |
| 145 | |
| 146 XWindowAttributes attributes; | |
| 147 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) { | |
| 148 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; | |
| 149 return false; | |
| 150 } | |
| 151 | |
| 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; | |
| 156 } | |
| 157 if (pixmap_) { | |
| 158 XFreePixmap(g_osmesa_display, pixmap_); | |
| 159 pixmap_ = 0; | |
| 160 } | |
| 161 | |
| 162 // Recreate a pixmap to hold the frame. | |
| 163 pixmap_ = XCreatePixmap(g_osmesa_display, | |
| 164 window_, | |
| 165 new_size.width(), | |
| 166 new_size.height(), | |
| 167 attributes.depth); | |
| 168 if (!pixmap_) { | |
| 169 LOG(ERROR) << "XCreatePixmap failed."; | |
| 170 return false; | |
| 171 } | |
| 172 | |
| 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"; | |
| 177 return false; | |
| 178 } | |
| 179 | |
| 180 return true; | |
| 181 } | |
| 182 | |
| 183 bool NativeViewGLSurfaceOSMesa::IsOffscreen() { | |
| 184 return false; | |
| 185 } | |
| 186 | |
| 187 bool NativeViewGLSurfaceOSMesa::SwapBuffers() { | |
| 188 gfx::Size size = GetSize(); | |
| 189 | |
| 190 XWindowAttributes attributes; | |
| 191 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) { | |
| 192 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; | |
| 193 return false; | |
| 194 } | |
| 195 | |
| 196 // Copy the frame into the pixmap. | |
| 197 ui::PutARGBImage(g_osmesa_display, | |
| 198 attributes.visual, | |
| 199 attributes.depth, | |
| 200 pixmap_, | |
| 201 pixmap_graphics_context_, | |
| 202 static_cast<const uint8*>(GetHandle()), | |
| 203 size.width(), | |
| 204 size.height()); | |
| 205 | |
| 206 // Copy the pixmap to the window. | |
| 207 XCopyArea(g_osmesa_display, | |
| 208 pixmap_, | |
| 209 window_, | |
| 210 window_graphics_context_, | |
| 211 0, 0, | |
| 212 size.width(), size.height(), | |
| 213 0, 0); | |
| 214 | |
| 215 return true; | |
| 216 } | |
| 217 | |
| 218 std::string NativeViewGLSurfaceOSMesa::GetExtensions() { | |
| 219 std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions(); | |
| 220 extensions += extensions.empty() ? "" : " "; | |
| 221 extensions += "GL_CHROMIUM_post_sub_buffer"; | |
| 222 return extensions; | |
| 223 } | |
| 224 | |
| 225 bool NativeViewGLSurfaceOSMesa::PostSubBuffer( | |
| 226 int x, int y, int width, int height) { | |
| 227 gfx::Size size = GetSize(); | |
| 228 | |
| 229 // Move (0,0) from lower-left to upper-left | |
| 230 y = size.height() - y - height; | |
| 231 | |
| 232 XWindowAttributes attributes; | |
| 233 if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) { | |
| 234 LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; | |
| 235 return false; | |
| 236 } | |
| 237 | |
| 238 // Copy the frame into the pixmap. | |
| 239 ui::PutARGBImage(g_osmesa_display, | |
| 240 attributes.visual, | |
| 241 attributes.depth, | |
| 242 pixmap_, | |
| 243 pixmap_graphics_context_, | |
| 244 static_cast<const uint8*>(GetHandle()), | |
| 245 size.width(), | |
| 246 size.height(), | |
| 247 x, y, | |
| 248 x, y, | |
| 249 width, | |
| 250 height); | |
| 251 | |
| 252 // Copy the pixmap to the window. | |
| 253 XCopyArea(g_osmesa_display, | |
| 254 pixmap_, | |
| 255 window_, | |
| 256 window_graphics_context_, | |
| 257 x, y, | |
| 258 width, height, | |
| 259 x, y); | |
| 260 | |
| 261 return true; | |
| 262 } | |
| 263 | |
| 264 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() { | |
| 265 Destroy(); | |
| 266 } | |
| 267 | |
| 268 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( | |
| 269 bool software, | |
| 270 gfx::AcceleratedWidget window) { | |
| 271 TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface"); | |
| 272 if (software) | |
| 273 return NULL; | |
| 274 | |
| 275 switch (GetGLImplementation()) { | |
| 276 case kGLImplementationOSMesaGL: { | |
| 277 scoped_refptr<GLSurface> surface( | |
| 278 new NativeViewGLSurfaceOSMesa(window)); | |
| 279 if (!surface->Initialize()) | |
| 280 return NULL; | |
| 281 | |
| 282 return surface; | |
| 283 } | |
| 284 case kGLImplementationDesktopGL: { | |
| 285 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX( | |
| 286 window)); | |
| 287 if (!surface->Initialize()) | |
| 288 return NULL; | |
| 289 | |
| 290 return surface; | |
| 291 } | |
| 292 case kGLImplementationEGLGLES2: { | |
| 293 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL( | |
| 294 false, window)); | |
| 295 if (!surface->Initialize()) | |
| 296 return NULL; | |
| 297 | |
| 298 return surface; | |
| 299 } | |
| 300 case kGLImplementationMockGL: | |
| 301 return new GLSurfaceStub; | |
| 302 default: | |
| 303 NOTREACHED(); | |
| 304 return NULL; | |
| 305 } | |
| 306 } | |
| 307 | |
| 308 scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface( | |
| 309 bool software, | |
| 310 const gfx::Size& size) { | |
| 311 TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface"); | |
| 312 if (software) | |
| 313 return NULL; | |
| 314 | |
| 315 switch (GetGLImplementation()) { | |
| 316 case kGLImplementationOSMesaGL: { | |
| 317 scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA, | |
| 318 size)); | |
| 319 if (!surface->Initialize()) | |
| 320 return NULL; | |
| 321 | |
| 322 return surface; | |
| 323 } | |
| 324 case kGLImplementationDesktopGL: { | |
| 325 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceGLX(size)); | |
| 326 if (!surface->Initialize()) | |
| 327 return NULL; | |
| 328 | |
| 329 return surface; | |
| 330 } | |
| 331 case kGLImplementationEGLGLES2: { | |
| 332 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(false, size)); | |
| 333 if (!surface->Initialize()) | |
| 334 return NULL; | |
| 335 | |
| 336 return surface; | |
| 337 } | |
| 338 case kGLImplementationMockGL: | |
| 339 return new GLSurfaceStub; | |
| 340 default: | |
| 341 NOTREACHED(); | |
| 342 return NULL; | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 } // namespace gfx | |
| OLD | NEW |