summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorjbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-06 09:31:37 +0000
committerjbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-06 09:31:37 +0000
commitcd195afe71821ee888fbe455ea770f9b41a19028 (patch)
treeee9587b9e9347f7301395440618573b407982ed7 /ui
parent4cc3982df8ddcf12b7cd791dfbb94a1d206767b2 (diff)
downloadchromium_src-cd195afe71821ee888fbe455ea770f9b41a19028.zip
chromium_src-cd195afe71821ee888fbe455ea770f9b41a19028.tar.gz
chromium_src-cd195afe71821ee888fbe455ea770f9b41a19028.tar.bz2
Switch all contexts in a share group to be on the same screen as the window they present to.
When OS X switches GPUs, some contexts that were created beforehand and aren't associated with an NSView can be left behind on the old GPU, which will cause problems when other contexts attempt to share textures with them. To fix this, track what renderer is being used to present to the screen, transmit that to the IOSurfaceImageTransportSurface in the GPU process, and change every context in the same share group to use that renderer. BUG=174149 Review URL: https://chromiumcodereview.appspot.com/12383042 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186388 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/gl/gl_context_cgl.cc93
-rw-r--r--ui/gl/gl_context_cgl.h3
-rw-r--r--ui/gl/gl_share_group.cc16
-rw-r--r--ui/gl/gl_share_group.h11
4 files changed, 98 insertions, 25 deletions
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc
index cdd84ba..beda807 100644
--- a/ui/gl/gl_context_cgl.cc
+++ b/ui/gl/gl_context_cgl.cc
@@ -17,47 +17,63 @@
namespace gfx {
-GLContextCGL::GLContextCGL(GLShareGroup* share_group)
- : GLContext(share_group),
- context_(NULL),
- gpu_preference_(PreferIntegratedGpu),
- discrete_pixelformat_(NULL) {
-}
-
-bool GLContextCGL::Initialize(GLSurface* compatible_surface,
- GpuPreference gpu_preference) {
- DCHECK(compatible_surface);
-
- gpu_preference = ui::GpuSwitchingManager::GetInstance()->AdjustGpuPreference(
- gpu_preference);
-
- GLContextCGL* share_context = share_group() ?
- static_cast<GLContextCGL*>(share_group()->GetContext()) : NULL;
+bool g_support_renderer_switching;
+static CGLPixelFormatObj GetPixelFormat() {
+ static CGLPixelFormatObj format;
+ if (format)
+ return format;
std::vector<CGLPixelFormatAttribute> attribs;
// If the system supports dual gpus then allow offline renderers for every
// context, so that they can all be in the same share group.
- if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
+ if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
attribs.push_back(kCGLPFAAllowOfflineRenderers);
+ g_support_renderer_switching = true;
+ }
if (GetGLImplementation() == kGLImplementationAppleGL) {
attribs.push_back(kCGLPFARendererID);
attribs.push_back((CGLPixelFormatAttribute) kCGLRendererGenericFloatID);
+ g_support_renderer_switching = false;
}
attribs.push_back((CGLPixelFormatAttribute) 0);
- CGLPixelFormatObj format;
- GLint num_pixel_formats;
+ GLint num_virtual_screens;
if (CGLChoosePixelFormat(&attribs.front(),
&format,
- &num_pixel_formats) != kCGLNoError) {
+ &num_virtual_screens) != kCGLNoError) {
LOG(ERROR) << "Error choosing pixel format.";
- return false;
+ return NULL;
}
if (!format) {
LOG(ERROR) << "format == 0.";
- return false;
+ return NULL;
}
- DCHECK_NE(num_pixel_formats, 0);
+ DCHECK_NE(num_virtual_screens, 0);
+ return format;
+}
+
+GLContextCGL::GLContextCGL(GLShareGroup* share_group)
+ : GLContext(share_group),
+ context_(NULL),
+ gpu_preference_(PreferIntegratedGpu),
+ discrete_pixelformat_(NULL),
+ screen_(-1),
+ renderer_id_(-1) {
+}
+
+bool GLContextCGL::Initialize(GLSurface* compatible_surface,
+ GpuPreference gpu_preference) {
+ DCHECK(compatible_surface);
+
+ gpu_preference = ui::GpuSwitchingManager::GetInstance()->AdjustGpuPreference(
+ gpu_preference);
+
+ GLContextCGL* share_context = share_group() ?
+ static_cast<GLContextCGL*>(share_group()->GetContext()) : NULL;
+
+ CGLPixelFormatObj format = GetPixelFormat();
+ if (!format)
+ return false;
// If using the discrete gpu, create a pixel format requiring it before we
// create the context.
@@ -79,7 +95,6 @@ bool GLContextCGL::Initialize(GLSurface* compatible_surface,
share_context ?
static_cast<CGLContextObj>(share_context->GetHandle()) : NULL,
reinterpret_cast<CGLContextObj*>(&context_));
- CGLReleasePixelFormat(format);
if (res != kCGLNoError) {
LOG(ERROR) << "Error creating context.";
Destroy();
@@ -103,6 +118,36 @@ void GLContextCGL::Destroy() {
bool GLContextCGL::MakeCurrent(GLSurface* surface) {
DCHECK(context_);
+ int renderer_id = share_group()->GetRendererID();
+ int screen;
+ CGLGetVirtualScreen(static_cast<CGLContextObj>(context_), &screen);
+
+ if (g_support_renderer_switching &&
+ (screen != screen_ || renderer_id != renderer_id_)) {
+ CGLPixelFormatObj format = GetPixelFormat();
+ // Attempt to find a virtual screen that's using the requested renderer,
+ // and switch the context to use that screen.
+ int virtual_screen_count;
+ if (CGLDescribePixelFormat(format, 0, kCGLPFAVirtualScreenCount,
+ &virtual_screen_count) != kCGLNoError)
+ return false;
+
+ for (int i = 0; i < virtual_screen_count; ++i) {
+ int screen_renderer_id;
+ if (CGLDescribePixelFormat(format, i, kCGLPFARendererID,
+ &screen_renderer_id) != kCGLNoError)
+ return false;
+
+ screen_renderer_id &= kCGLRendererIDMatchingMask;
+ if (screen_renderer_id == renderer_id) {
+ CGLSetVirtualScreen(static_cast<CGLContextObj>(context_), i);
+ screen_ = i;
+ break;
+ }
+ }
+ renderer_id_ = renderer_id;
+ }
+
if (IsCurrent(surface))
return true;
diff --git a/ui/gl/gl_context_cgl.h b/ui/gl/gl_context_cgl.h
index 3e4e3c1..bad2e3a 100644
--- a/ui/gl/gl_context_cgl.h
+++ b/ui/gl/gl_context_cgl.h
@@ -41,6 +41,9 @@ class GLContextCGL : public GLContext {
CGLPixelFormatObj discrete_pixelformat_;
+ int screen_;
+ int renderer_id_;
+
DISALLOW_COPY_AND_ASSIGN(GLContextCGL);
};
diff --git a/ui/gl/gl_share_group.cc b/ui/gl/gl_share_group.cc
index 34f7c7f..8e8958b 100644
--- a/ui/gl/gl_share_group.cc
+++ b/ui/gl/gl_share_group.cc
@@ -10,7 +10,11 @@
namespace gfx {
GLShareGroup::GLShareGroup()
- : shared_context_(NULL) {
+ : shared_context_(NULL)
+#if defined(OS_MACOSX)
+ , renderer_id_(-1)
+#endif
+ {
}
void GLShareGroup::AddContext(GLContext* context) {
@@ -51,6 +55,16 @@ GLContext* GLShareGroup::GetSharedContext() {
return shared_context_;
}
+#if defined(OS_MACOSX)
+void GLShareGroup::SetRendererID(int renderer_id) {
+ renderer_id_ = renderer_id;
+}
+
+int GLShareGroup::GetRendererID() {
+ return renderer_id_;
+}
+#endif
+
GLShareGroup::~GLShareGroup() {
}
diff --git a/ui/gl/gl_share_group.h b/ui/gl/gl_share_group.h
index e069d65..1deed63 100644
--- a/ui/gl/gl_share_group.h
+++ b/ui/gl/gl_share_group.h
@@ -38,6 +38,13 @@ class GL_EXPORT GLShareGroup : public base::RefCounted<GLShareGroup> {
void SetSharedContext(GLContext* context);
GLContext* GetSharedContext();
+#if defined(OS_MACOSX)
+ // Sets and returns the ID of the renderer that all contexts in this share
+ // group should be on.
+ void SetRendererID(int renderer_id);
+ int GetRendererID();
+#endif
+
private:
friend class base::RefCounted<GLShareGroup>;
@@ -50,6 +57,10 @@ class GL_EXPORT GLShareGroup : public base::RefCounted<GLShareGroup> {
GLContext* shared_context_;
+#if defined(OS_MACOSX)
+ int renderer_id_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(GLShareGroup);
};