Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 extern "C" { | 5 extern "C" { |
| 6 #include <X11/Xlib.h> | 6 #include <X11/Xlib.h> |
| 7 } | 7 } |
| 8 | 8 |
| 9 #include "ui/gl/gl_surface_glx.h" | 9 #include "ui/gl/gl_surface_glx.h" |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 #include "ui/gfx/x/x11_connection.h" | 26 #include "ui/gfx/x/x11_connection.h" |
| 27 #include "ui/gfx/x/x11_types.h" | 27 #include "ui/gfx/x/x11_types.h" |
| 28 #include "ui/gl/gl_bindings.h" | 28 #include "ui/gl/gl_bindings.h" |
| 29 #include "ui/gl/gl_implementation.h" | 29 #include "ui/gl/gl_implementation.h" |
| 30 #include "ui/gl/sync_control_vsync_provider.h" | 30 #include "ui/gl/sync_control_vsync_provider.h" |
| 31 | 31 |
| 32 namespace gfx { | 32 namespace gfx { |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 Display* g_display = NULL; | 36 Display* g_display = nullptr; |
| 37 const char* g_glx_extensions = NULL; | 37 const char* g_glx_extensions = nullptr; |
| 38 bool g_glx_context_create = false; | 38 bool g_glx_context_create = false; |
| 39 bool g_glx_create_context_robustness_supported = false; | 39 bool g_glx_create_context_robustness_supported = false; |
| 40 bool g_glx_texture_from_pixmap_supported = false; | 40 bool g_glx_texture_from_pixmap_supported = false; |
| 41 bool g_glx_oml_sync_control_supported = false; | 41 bool g_glx_oml_sync_control_supported = false; |
| 42 | 42 |
| 43 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a | 43 // Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a |
| 44 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML | 44 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML |
| 45 // always fails even though GLX_OML_sync_control is reported as being supported. | 45 // always fails even though GLX_OML_sync_control is reported as being supported. |
| 46 bool g_glx_get_msc_rate_oml_supported = false; | 46 bool g_glx_get_msc_rate_oml_supported = false; |
| 47 | 47 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 | 113 |
| 114 private: | 114 private: |
| 115 friend class base::RefCounted<SGIVideoSyncThread>; | 115 friend class base::RefCounted<SGIVideoSyncThread>; |
| 116 | 116 |
| 117 SGIVideoSyncThread() : base::Thread("SGI_video_sync") { | 117 SGIVideoSyncThread() : base::Thread("SGI_video_sync") { |
| 118 DCHECK(CalledOnValidThread()); | 118 DCHECK(CalledOnValidThread()); |
| 119 } | 119 } |
| 120 | 120 |
| 121 ~SGIVideoSyncThread() override { | 121 ~SGIVideoSyncThread() override { |
| 122 DCHECK(CalledOnValidThread()); | 122 DCHECK(CalledOnValidThread()); |
| 123 g_video_sync_thread = NULL; | 123 g_video_sync_thread = nullptr; |
| 124 Stop(); | 124 Stop(); |
| 125 } | 125 } |
| 126 | 126 |
| 127 static SGIVideoSyncThread* g_video_sync_thread; | 127 static SGIVideoSyncThread* g_video_sync_thread; |
| 128 | 128 |
| 129 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncThread); | 129 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncThread); |
| 130 }; | 130 }; |
| 131 | 131 |
| 132 class SGIVideoSyncProviderThreadShim { | 132 class SGIVideoSyncProviderThreadShim { |
| 133 public: | 133 public: |
| 134 explicit SGIVideoSyncProviderThreadShim(XID window) | 134 explicit SGIVideoSyncProviderThreadShim(XID window) |
| 135 : window_(window), | 135 : window_(window), |
| 136 context_(NULL), | 136 context_(nullptr), |
| 137 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 137 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 138 cancel_vsync_flag_(), | 138 cancel_vsync_flag_(), |
| 139 vsync_lock_() { | 139 vsync_lock_() { |
| 140 // This ensures that creation of |window_| has occured when this shim | 140 // This ensures that creation of |window_| has occured when this shim |
| 141 // is executing in the same process as the call to create |window_|. | 141 // is executing in the same process as the call to create |window_|. |
| 142 XSync(g_display, False); | 142 XSync(g_display, False); |
| 143 } | 143 } |
| 144 | 144 |
| 145 virtual ~SGIVideoSyncProviderThreadShim() { | 145 virtual ~SGIVideoSyncProviderThreadShim() { |
| 146 if (context_) { | 146 if (context_) { |
| 147 glXDestroyContext(display_, context_); | 147 glXDestroyContext(display_, context_); |
| 148 context_ = NULL; | 148 context_ = nullptr; |
| 149 } | 149 } |
| 150 } | 150 } |
| 151 | 151 |
| 152 base::CancellationFlag* cancel_vsync_flag() { | 152 base::CancellationFlag* cancel_vsync_flag() { |
| 153 return &cancel_vsync_flag_; | 153 return &cancel_vsync_flag_; |
| 154 } | 154 } |
| 155 | 155 |
| 156 base::Lock* vsync_lock() { | 156 base::Lock* vsync_lock() { |
| 157 return &vsync_lock_; | 157 return &vsync_lock_; |
| 158 } | 158 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 173 int visual_info_count = 0; | 173 int visual_info_count = 0; |
| 174 gfx::XScopedPtr<XVisualInfo> visual_info_list(XGetVisualInfo( | 174 gfx::XScopedPtr<XVisualInfo> visual_info_list(XGetVisualInfo( |
| 175 display_, VisualIDMask, &visual_info_template, &visual_info_count)); | 175 display_, VisualIDMask, &visual_info_template, &visual_info_count)); |
| 176 | 176 |
| 177 DCHECK(visual_info_list.get()); | 177 DCHECK(visual_info_list.get()); |
| 178 if (visual_info_count == 0) { | 178 if (visual_info_count == 0) { |
| 179 LOG(ERROR) << "No visual info for visual ID."; | 179 LOG(ERROR) << "No visual info for visual ID."; |
| 180 return; | 180 return; |
| 181 } | 181 } |
| 182 | 182 |
| 183 context_ = glXCreateContext(display_, visual_info_list.get(), NULL, True); | 183 context_ = |
| 184 glXCreateContext(display_, visual_info_list.get(), nullptr, True); | |
| 184 | 185 |
| 185 DCHECK(NULL != context_); | 186 DCHECK(nullptr != context_); |
| 186 } | 187 } |
| 187 | 188 |
| 188 void GetVSyncParameters(const VSyncProvider::UpdateVSyncCallback& callback) { | 189 void GetVSyncParameters(const VSyncProvider::UpdateVSyncCallback& callback) { |
| 189 base::TimeTicks now; | 190 base::TimeTicks now; |
| 190 { | 191 { |
| 191 // Don't allow |window_| destruction while we're probing vsync. | 192 // Don't allow |window_| destruction while we're probing vsync. |
| 192 base::AutoLock locked(vsync_lock_); | 193 base::AutoLock locked(vsync_lock_); |
| 193 | 194 |
| 194 if (!context_ || cancel_vsync_flag_.IsSet()) | 195 if (!context_ || cancel_vsync_flag_.IsSet()) |
| 195 return; | 196 return; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 // These will only be referenced before we post a task to destroy | 302 // These will only be referenced before we post a task to destroy |
| 302 // the shim_, so they are safe to access. | 303 // the shim_, so they are safe to access. |
| 303 base::CancellationFlag* cancel_vsync_flag_; | 304 base::CancellationFlag* cancel_vsync_flag_; |
| 304 base::Lock* vsync_lock_; | 305 base::Lock* vsync_lock_; |
| 305 | 306 |
| 306 base::TimeTicks last_get_vsync_parameters_time_; | 307 base::TimeTicks last_get_vsync_parameters_time_; |
| 307 | 308 |
| 308 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); | 309 DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncVSyncProvider); |
| 309 }; | 310 }; |
| 310 | 311 |
| 311 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL; | 312 SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = nullptr; |
| 312 | 313 |
| 313 // In order to take advantage of GLX_SGI_video_sync, we need a display | 314 // In order to take advantage of GLX_SGI_video_sync, we need a display |
| 314 // for use on a separate thread. We must allocate this before the sandbox | 315 // for use on a separate thread. We must allocate this before the sandbox |
| 315 // goes up (rather than on-demand when we start the thread). | 316 // goes up (rather than on-demand when we start the thread). |
| 316 Display* SGIVideoSyncProviderThreadShim::display_ = NULL; | 317 Display* SGIVideoSyncProviderThreadShim::display_ = nullptr; |
| 317 | 318 |
| 318 } // namespace | 319 } // namespace |
| 319 | 320 |
| 320 GLSurfaceGLX::GLSurfaceGLX() {} | 321 GLSurfaceGLX::GLSurfaceGLX() {} |
| 321 | 322 |
| 322 bool GLSurfaceGLX::InitializeOneOff() { | 323 bool GLSurfaceGLX::InitializeOneOff() { |
| 323 static bool initialized = false; | 324 static bool initialized = false; |
| 324 if (initialized) | 325 if (initialized) |
| 325 return true; | 326 return true; |
| 326 | 327 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 397 bool GLSurfaceGLX::IsOMLSyncControlSupported() { | 398 bool GLSurfaceGLX::IsOMLSyncControlSupported() { |
| 398 return g_glx_oml_sync_control_supported; | 399 return g_glx_oml_sync_control_supported; |
| 399 } | 400 } |
| 400 | 401 |
| 401 void* GLSurfaceGLX::GetDisplay() { | 402 void* GLSurfaceGLX::GetDisplay() { |
| 402 return g_display; | 403 return g_display; |
| 403 } | 404 } |
| 404 | 405 |
| 405 GLSurfaceGLX::~GLSurfaceGLX() {} | 406 GLSurfaceGLX::~GLSurfaceGLX() {} |
| 406 | 407 |
| 408 void* GLSurfaceGLX::GetConfig(gfx::AcceleratedWidget window) { | |
| 409 DCHECK(window != 0); | |
| 410 | |
| 411 // This code path is expensive, but we only take it when | |
| 412 // attempting to use GLX_ARB_create_context_robustness, in which | |
| 413 // case we need a GLXFBConfig for the window in order to create a | |
| 414 // context for it. | |
| 415 // | |
| 416 // TODO(kbr): this is not a reliable code path. On platforms which | |
| 417 // support it, we should use glXChooseFBConfig in the browser | |
| 418 // process to choose the FBConfig and from there the X Visual to | |
| 419 // use when creating the window in the first place. Then we can | |
| 420 // pass that FBConfig down rather than attempting to reconstitute | |
| 421 // it. | |
| 422 | |
| 423 XWindowAttributes attributes; | |
| 424 if (!XGetWindowAttributes(g_display, window, &attributes)) { | |
| 425 LOG(ERROR) << "XGetWindowAttributes failed for window " << window << "."; | |
| 426 return nullptr; | |
| 427 } | |
| 428 | |
| 429 int visual_id = XVisualIDFromVisual(attributes.visual); | |
| 430 | |
| 431 int num_elements = 0; | |
| 432 gfx::XScopedPtr<GLXFBConfig> configs( | |
| 433 glXGetFBConfigs(g_display, DefaultScreen(g_display), &num_elements)); | |
| 434 if (!configs.get()) { | |
| 435 LOG(ERROR) << "glXGetFBConfigs failed."; | |
| 436 return nullptr; | |
| 437 } | |
| 438 if (!num_elements) { | |
| 439 LOG(ERROR) << "glXGetFBConfigs returned 0 elements."; | |
| 440 return nullptr; | |
| 441 } | |
| 442 bool found = false; | |
| 443 int i; | |
| 444 for (i = 0; i < num_elements; ++i) { | |
| 445 int value; | |
| 446 if (glXGetFBConfigAttrib(g_display, configs.get()[i], GLX_VISUAL_ID, | |
| 447 &value)) { | |
| 448 LOG(ERROR) << "glXGetFBConfigAttrib failed."; | |
| 449 return nullptr; | |
| 450 } | |
| 451 if (value == visual_id) { | |
| 452 found = true; | |
| 453 break; | |
| 454 } | |
| 455 } | |
| 456 if (found) { | |
| 457 return configs.get()[i]; | |
| 458 } | |
| 459 return nullptr; | |
| 460 } | |
| 461 | |
| 407 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) | 462 NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window) |
| 408 : parent_window_(window), | 463 : parent_window_(window), window_(0), config_(nullptr) { |
| 409 window_(0), | |
| 410 config_(NULL) { | |
| 411 } | 464 } |
| 412 | 465 |
| 413 gfx::AcceleratedWidget NativeViewGLSurfaceGLX::GetDrawableHandle() const { | 466 gfx::AcceleratedWidget NativeViewGLSurfaceGLX::GetDrawableHandle() const { |
| 414 return window_; | 467 return window_; |
| 415 } | 468 } |
| 416 | 469 |
| 417 bool NativeViewGLSurfaceGLX::Initialize() { | 470 bool NativeViewGLSurfaceGLX::Initialize() { |
| 418 XWindowAttributes attributes; | 471 XWindowAttributes attributes; |
| 419 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) { | 472 if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) { |
| 420 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_ | 473 LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_ |
| 421 << "."; | 474 << "."; |
| 422 return false; | 475 return false; |
| 423 } | 476 } |
| 424 size_ = gfx::Size(attributes.width, attributes.height); | 477 size_ = gfx::Size(attributes.width, attributes.height); |
| 425 // Create a child window, with a CopyFromParent visual (to avoid inducing | 478 // Create a child window, with a CopyFromParent visual (to avoid inducing |
| 426 // extra blits in the driver), that we can resize exactly in Resize(), | 479 // extra blits in the driver), that we can resize exactly in Resize(), |
| 427 // correctly ordered with GL, so that we don't have invalid transient states. | 480 // correctly ordered with GL, so that we don't have invalid transient states. |
| 428 // See https://crbug.com/326995. | 481 // See https://crbug.com/326995. |
| 429 window_ = XCreateWindow(g_display, | 482 window_ = XCreateWindow(g_display, parent_window_, 0, 0, size_.width(), |
| 430 parent_window_, | 483 size_.height(), 0, CopyFromParent, InputOutput, |
| 431 0, | 484 CopyFromParent, 0, nullptr); |
| 432 0, | |
| 433 size_.width(), | |
| 434 size_.height(), | |
| 435 0, | |
| 436 CopyFromParent, | |
| 437 InputOutput, | |
| 438 CopyFromParent, | |
| 439 0, | |
| 440 NULL); | |
| 441 XMapWindow(g_display, window_); | 485 XMapWindow(g_display, window_); |
| 442 | 486 |
| 443 ui::PlatformEventSource* event_source = | 487 ui::PlatformEventSource* event_source = |
| 444 ui::PlatformEventSource::GetInstance(); | 488 ui::PlatformEventSource::GetInstance(); |
| 445 // Can be NULL in tests, when we don't care about Exposes. | 489 // Can be nullptr in tests, when we don't care about Exposes. |
| 446 if (event_source) { | 490 if (event_source) { |
| 447 XSelectInput(g_display, window_, ExposureMask); | 491 XSelectInput(g_display, window_, ExposureMask); |
| 448 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); | 492 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); |
| 449 } | 493 } |
| 450 XFlush(g_display); | 494 XFlush(g_display); |
| 451 | 495 |
| 452 gfx::AcceleratedWidget window_for_vsync = window_; | 496 gfx::AcceleratedWidget window_for_vsync = window_; |
| 453 | 497 |
| 454 if (g_glx_oml_sync_control_supported) | 498 if (g_glx_oml_sync_control_supported) |
| 455 vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_for_vsync)); | 499 vsync_provider_.reset(new OMLSyncControlVSyncProvider(window_for_vsync)); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 511 | 555 |
| 512 void* NativeViewGLSurfaceGLX::GetHandle() { | 556 void* NativeViewGLSurfaceGLX::GetHandle() { |
| 513 return reinterpret_cast<void*>(GetDrawableHandle()); | 557 return reinterpret_cast<void*>(GetDrawableHandle()); |
| 514 } | 558 } |
| 515 | 559 |
| 516 bool NativeViewGLSurfaceGLX::SupportsPostSubBuffer() { | 560 bool NativeViewGLSurfaceGLX::SupportsPostSubBuffer() { |
| 517 return gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer; | 561 return gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer; |
| 518 } | 562 } |
| 519 | 563 |
| 520 void* NativeViewGLSurfaceGLX::GetConfig() { | 564 void* NativeViewGLSurfaceGLX::GetConfig() { |
| 521 if (!config_) { | 565 if (!config_) |
| 522 // This code path is expensive, but we only take it when | 566 config_ = GLSurfaceGLX::GetConfig(window_); |
| 523 // attempting to use GLX_ARB_create_context_robustness, in which | |
| 524 // case we need a GLXFBConfig for the window in order to create a | |
| 525 // context for it. | |
| 526 // | |
| 527 // TODO(kbr): this is not a reliable code path. On platforms which | |
| 528 // support it, we should use glXChooseFBConfig in the browser | |
| 529 // process to choose the FBConfig and from there the X Visual to | |
| 530 // use when creating the window in the first place. Then we can | |
| 531 // pass that FBConfig down rather than attempting to reconstitute | |
| 532 // it. | |
| 533 | |
| 534 XWindowAttributes attributes; | |
| 535 if (!XGetWindowAttributes( | |
| 536 g_display, | |
| 537 window_, | |
| 538 &attributes)) { | |
| 539 LOG(ERROR) << "XGetWindowAttributes failed for window " << | |
| 540 window_ << "."; | |
| 541 return NULL; | |
| 542 } | |
| 543 | |
| 544 int visual_id = XVisualIDFromVisual(attributes.visual); | |
| 545 | |
| 546 int num_elements = 0; | |
| 547 gfx::XScopedPtr<GLXFBConfig> configs( | |
| 548 glXGetFBConfigs(g_display, DefaultScreen(g_display), &num_elements)); | |
| 549 if (!configs.get()) { | |
| 550 LOG(ERROR) << "glXGetFBConfigs failed."; | |
| 551 return NULL; | |
| 552 } | |
| 553 if (!num_elements) { | |
| 554 LOG(ERROR) << "glXGetFBConfigs returned 0 elements."; | |
| 555 return NULL; | |
| 556 } | |
| 557 bool found = false; | |
| 558 int i; | |
| 559 for (i = 0; i < num_elements; ++i) { | |
| 560 int value; | |
| 561 if (glXGetFBConfigAttrib( | |
| 562 g_display, configs.get()[i], GLX_VISUAL_ID, &value)) { | |
| 563 LOG(ERROR) << "glXGetFBConfigAttrib failed."; | |
| 564 return NULL; | |
| 565 } | |
| 566 if (value == visual_id) { | |
| 567 found = true; | |
| 568 break; | |
| 569 } | |
| 570 } | |
| 571 if (found) { | |
| 572 config_ = configs.get()[i]; | |
| 573 } | |
| 574 } | |
| 575 | |
| 576 return config_; | 567 return config_; |
| 577 } | 568 } |
| 578 | 569 |
| 579 bool NativeViewGLSurfaceGLX::PostSubBuffer( | 570 bool NativeViewGLSurfaceGLX::PostSubBuffer( |
| 580 int x, int y, int width, int height) { | 571 int x, int y, int width, int height) { |
| 581 DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); | 572 DCHECK(gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer); |
| 582 glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height); | 573 glXCopySubBufferMESA(g_display, GetDrawableHandle(), x, y, width, height); |
| 583 return true; | 574 return true; |
| 584 } | 575 } |
| 585 | 576 |
| 586 VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { | 577 VSyncProvider* NativeViewGLSurfaceGLX::GetVSyncProvider() { |
| 587 return vsync_provider_.get(); | 578 return vsync_provider_.get(); |
| 588 } | 579 } |
| 589 | 580 |
| 590 NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { | 581 NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { |
| 591 Destroy(); | 582 Destroy(); |
| 592 } | 583 } |
| 593 | 584 |
| 594 PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size) | 585 UnmappedNativeViewGLSurfaceGLX::UnmappedNativeViewGLSurfaceGLX( |
| 595 : size_(size), | 586 const gfx::Size& size) |
| 596 config_(NULL), | 587 : size_(size), config_(nullptr), window_(0) { |
| 597 pbuffer_(0) { | 588 // Ensure that we don't create a window with zero size. |
| 598 // Some implementations of Pbuffer do not support having a 0 size. For such | |
| 599 // cases use a (1, 1) surface. | |
| 600 if (size_.GetArea() == 0) | 589 if (size_.GetArea() == 0) |
|
hendrikw
2015/04/17 18:59:46
I think it's safer to leave this in, but it would
piman
2015/04/17 19:37:29
AIUI yes it's needed. XCreatWindow(3) isn't clear
| |
| 601 size_.SetSize(1, 1); | 590 size_.SetSize(1, 1); |
| 602 } | 591 } |
| 603 | 592 |
| 604 bool PbufferGLSurfaceGLX::Initialize() { | 593 bool UnmappedNativeViewGLSurfaceGLX::Initialize() { |
| 605 DCHECK(!pbuffer_); | 594 DCHECK(!window_); |
| 606 | 595 |
| 607 static const int config_attributes[] = { | 596 gfx::AcceleratedWidget parent_window = |
| 608 GLX_BUFFER_SIZE, 32, | 597 RootWindow(g_display, DefaultScreen(g_display)); |
| 609 GLX_ALPHA_SIZE, 8, | |
| 610 GLX_BLUE_SIZE, 8, | |
| 611 GLX_GREEN_SIZE, 8, | |
| 612 GLX_RED_SIZE, 8, | |
| 613 GLX_RENDER_TYPE, GLX_RGBA_BIT, | |
| 614 GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, | |
| 615 GLX_DOUBLEBUFFER, False, | |
| 616 0 | |
| 617 }; | |
| 618 | 598 |
| 619 int num_elements = 0; | 599 // We create a window with CopyFromParent visual so that we have the same |
| 620 gfx::XScopedPtr<GLXFBConfig> configs(glXChooseFBConfig( | 600 // visual as NativeViewGLSurfaceGLX (i.e. same GLXFBConfig), to ensure |
| 621 g_display, DefaultScreen(g_display), config_attributes, &num_elements)); | 601 // contexts are compatible and can be made current with either. |
| 622 if (!configs.get()) { | 602 window_ = XCreateWindow(g_display, parent_window, 0, 0, size_.width(), |
| 623 LOG(ERROR) << "glXChooseFBConfig failed."; | 603 size_.height(), 0, CopyFromParent, InputOutput, |
| 624 return false; | 604 CopyFromParent, 0, nullptr); |
| 605 return window_ != 0; | |
| 606 } | |
| 607 | |
| 608 void UnmappedNativeViewGLSurfaceGLX::Destroy() { | |
| 609 config_ = nullptr; | |
| 610 if (window_) { | |
| 611 XDestroyWindow(g_display, window_); | |
| 612 window_ = 0; | |
| 625 } | 613 } |
| 626 if (!num_elements) { | 614 } |
| 627 LOG(ERROR) << "glXChooseFBConfig returned 0 elements."; | |
| 628 return false; | |
| 629 } | |
| 630 | 615 |
| 631 config_ = configs.get()[0]; | 616 bool UnmappedNativeViewGLSurfaceGLX::IsOffscreen() { |
| 632 | |
| 633 const int pbuffer_attributes[] = { | |
| 634 GLX_PBUFFER_WIDTH, size_.width(), | |
| 635 GLX_PBUFFER_HEIGHT, size_.height(), | |
| 636 0 | |
| 637 }; | |
| 638 pbuffer_ = glXCreatePbuffer(g_display, | |
| 639 static_cast<GLXFBConfig>(config_), | |
| 640 pbuffer_attributes); | |
| 641 if (!pbuffer_) { | |
| 642 Destroy(); | |
| 643 LOG(ERROR) << "glXCreatePbuffer failed."; | |
| 644 return false; | |
| 645 } | |
| 646 | |
| 647 return true; | 617 return true; |
| 648 } | 618 } |
| 649 | 619 |
| 650 void PbufferGLSurfaceGLX::Destroy() { | 620 bool UnmappedNativeViewGLSurfaceGLX::SwapBuffers() { |
| 651 if (pbuffer_) { | 621 NOTREACHED() << "Attempted to call SwapBuffers on an unmapped window."; |
| 652 glXDestroyPbuffer(g_display, pbuffer_); | |
| 653 pbuffer_ = 0; | |
| 654 } | |
| 655 | |
| 656 config_ = NULL; | |
| 657 } | |
| 658 | |
| 659 bool PbufferGLSurfaceGLX::IsOffscreen() { | |
| 660 return true; | |
| 661 } | |
| 662 | |
| 663 bool PbufferGLSurfaceGLX::SwapBuffers() { | |
| 664 NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer."; | |
| 665 return false; | 622 return false; |
| 666 } | 623 } |
| 667 | 624 |
| 668 gfx::Size PbufferGLSurfaceGLX::GetSize() { | 625 gfx::Size UnmappedNativeViewGLSurfaceGLX::GetSize() { |
| 669 return size_; | 626 return size_; |
| 670 } | 627 } |
| 671 | 628 |
| 672 void* PbufferGLSurfaceGLX::GetHandle() { | 629 void* UnmappedNativeViewGLSurfaceGLX::GetHandle() { |
| 673 return reinterpret_cast<void*>(pbuffer_); | 630 return reinterpret_cast<void*>(window_); |
| 674 } | 631 } |
| 675 | 632 |
| 676 void* PbufferGLSurfaceGLX::GetConfig() { | 633 void* UnmappedNativeViewGLSurfaceGLX::GetConfig() { |
| 634 if (!config_) | |
| 635 config_ = GLSurfaceGLX::GetConfig(window_); | |
| 677 return config_; | 636 return config_; |
| 678 } | 637 } |
| 679 | 638 |
| 680 PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() { | 639 UnmappedNativeViewGLSurfaceGLX::~UnmappedNativeViewGLSurfaceGLX() { |
| 681 Destroy(); | 640 Destroy(); |
| 682 } | 641 } |
| 683 | 642 |
| 684 } // namespace gfx | 643 } // namespace gfx |
| OLD | NEW |