Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / compositing_iosurface_context_mac.mm
1 // Copyright (c) 2013 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 "content/browser/renderer_host/compositing_iosurface_context_mac.h"
6
7 #include <OpenGL/gl.h>
8 #include <OpenGL/OpenGL.h>
9 #include <vector>
10
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/logging.h"
14 #include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
15 #include "ui/gl/gl_switches.h"
16 #include "ui/gl/gpu_switching_manager.h"
17
18 namespace content {
19
20 // static
21 scoped_refptr<CompositingIOSurfaceContext>
22 CompositingIOSurfaceContext::Get(int window_number) {
23   TRACE_EVENT0("browser", "CompositingIOSurfaceContext::Get");
24
25   // Return the context for this window_number, if it exists.
26   WindowMap::iterator found = window_map()->find(window_number);
27   if (found != window_map()->end()) {
28     DCHECK(found->second->can_be_shared_);
29     return found->second;
30   }
31
32   std::vector<NSOpenGLPixelFormatAttribute> attributes;
33   attributes.push_back(NSOpenGLPFADoubleBuffer);
34   // We don't need a depth buffer - try setting its size to 0...
35   attributes.push_back(NSOpenGLPFADepthSize); attributes.push_back(0);
36   if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
37     attributes.push_back(NSOpenGLPFAAllowOfflineRenderers);
38   attributes.push_back(0);
39
40   base::scoped_nsobject<NSOpenGLPixelFormat> glPixelFormat(
41       [[NSOpenGLPixelFormat alloc] initWithAttributes:&attributes.front()]);
42   if (!glPixelFormat) {
43     LOG(ERROR) << "NSOpenGLPixelFormat initWithAttributes failed";
44     return NULL;
45   }
46
47   // Create all contexts in the same share group so that the textures don't
48   // need to be recreated when transitioning contexts.
49   NSOpenGLContext* share_context = nil;
50   if (!window_map()->empty())
51     share_context = window_map()->begin()->second->nsgl_context();
52   base::scoped_nsobject<NSOpenGLContext> nsgl_context(
53       [[NSOpenGLContext alloc] initWithFormat:glPixelFormat
54                                  shareContext:share_context]);
55   if (!nsgl_context) {
56     LOG(ERROR) << "NSOpenGLContext initWithFormat failed";
57     return NULL;
58   }
59
60   CGLContextObj cgl_context = (CGLContextObj)[nsgl_context CGLContextObj];
61   if (!cgl_context) {
62     LOG(ERROR) << "CGLContextObj failed";
63     return NULL;
64   }
65
66   // Draw at beam vsync.
67   bool is_vsync_disabled =
68       CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync);
69   GLint swapInterval = is_vsync_disabled ? 0 : 1;
70   [nsgl_context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
71
72   // Prepare the shader program cache. Precompile the shader programs
73   // needed to draw the IO Surface for non-offscreen contexts.
74   CGLSetCurrentContext(cgl_context);
75   scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache(
76       new CompositingIOSurfaceShaderPrograms());
77   bool prepared = false;
78   if (window_number == kOffscreenContextWindowNumber) {
79     prepared = true;
80   } else {
81     prepared = (
82         shader_program_cache->UseBlitProgram() &&
83         shader_program_cache->UseSolidWhiteProgram());
84   }
85   glUseProgram(0u);
86   CGLSetCurrentContext(0);
87   if (!prepared) {
88     LOG(ERROR) << "IOSurface failed to compile/link required shader programs.";
89     return NULL;
90   }
91
92   return new CompositingIOSurfaceContext(
93       window_number,
94       nsgl_context.release(),
95       cgl_context,
96       is_vsync_disabled,
97       shader_program_cache.Pass());
98 }
99
100 // static
101 void CompositingIOSurfaceContext::MarkExistingContextsAsNotShareable() {
102   for (WindowMap::iterator it = window_map()->begin();
103        it != window_map()->end();
104        ++it) {
105     it->second->can_be_shared_ = false;
106   }
107   window_map()->clear();
108 }
109
110 CompositingIOSurfaceContext::CompositingIOSurfaceContext(
111     int window_number,
112     NSOpenGLContext* nsgl_context,
113     CGLContextObj cgl_context,
114     bool is_vsync_disabled,
115     scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache)
116     : window_number_(window_number),
117       nsgl_context_(nsgl_context),
118       cgl_context_(cgl_context),
119       is_vsync_disabled_(is_vsync_disabled),
120       shader_program_cache_(shader_program_cache.Pass()),
121       can_be_shared_(true),
122       initialized_is_intel_(false),
123       is_intel_(false),
124       screen_(0) {
125   DCHECK(window_map()->find(window_number_) == window_map()->end());
126   window_map()->insert(std::make_pair(window_number_, this));
127 }
128
129 CompositingIOSurfaceContext::~CompositingIOSurfaceContext() {
130   CGLSetCurrentContext(cgl_context_);
131   shader_program_cache_->Reset();
132   CGLSetCurrentContext(0);
133   if (can_be_shared_) {
134     DCHECK(window_map()->find(window_number_) != window_map()->end());
135     DCHECK(window_map()->find(window_number_)->second == this);
136     window_map()->erase(window_number_);
137   } else {
138     WindowMap::const_iterator found = window_map()->find(window_number_);
139     if (found != window_map()->end())
140       DCHECK(found->second != this);
141   }
142 }
143
144 bool CompositingIOSurfaceContext::IsVendorIntel() {
145   GLint screen;
146   CGLGetVirtualScreen(cgl_context(), &screen);
147   if (screen != screen_)
148     initialized_is_intel_ = false;
149   screen_ = screen;
150   if (!initialized_is_intel_) {
151     is_intel_ = strstr(reinterpret_cast<const char*>(glGetString(GL_VENDOR)),
152                       "Intel") != NULL;
153     initialized_is_intel_ = true;
154   }
155   return is_intel_;
156 }
157
158 // static
159 CompositingIOSurfaceContext::WindowMap*
160     CompositingIOSurfaceContext::window_map() {
161   return window_map_.Pointer();
162 }
163
164 // static
165 base::LazyInstance<CompositingIOSurfaceContext::WindowMap>
166     CompositingIOSurfaceContext::window_map_;
167
168 }  // namespace content