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 <algorithm>
8 #include <vector>
9
10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h"
12 #include "base/lazy_instance.h"
13 #include "base/logging.h"
14 #include "base/threading/thread_local.h"
15 #include "ui/gl/gl_context.h"
16 #include "ui/gl/gl_implementation.h"
17 #include "ui/gl/gl_switches.h"
18
19 #if defined(USE_X11)
20 #include <X11/Xlib.h>
21 #endif
22
23 namespace gfx {
24
25 namespace {
26 base::LazyInstance<base::ThreadLocalPointer<GLSurface> >::Leaky
27 current_surface_ = LAZY_INSTANCE_INITIALIZER;
28 } // namespace
29
30 // static
InitializeOneOff()31 bool GLSurface::InitializeOneOff() {
32 DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
33
34 TRACE_EVENT0("gpu", "GLSurface::InitializeOneOff");
35
36 std::vector<GLImplementation> allowed_impls;
37 GetAllowedGLImplementations(&allowed_impls);
38 DCHECK(!allowed_impls.empty());
39
40 CommandLine* cmd = CommandLine::ForCurrentProcess();
41
42 // The default implementation is always the first one in list.
43 GLImplementation impl = allowed_impls[0];
44 bool fallback_to_osmesa = false;
45 if (cmd->HasSwitch(switches::kOverrideUseGLWithOSMesaForTests)) {
46 impl = kGLImplementationOSMesaGL;
47 } else if (cmd->HasSwitch(switches::kUseGL)) {
48 std::string requested_implementation_name =
49 cmd->GetSwitchValueASCII(switches::kUseGL);
50 if (requested_implementation_name == "any") {
51 fallback_to_osmesa = true;
52 } else if (requested_implementation_name == "swiftshader") {
53 impl = kGLImplementationEGLGLES2;
54 } else {
55 impl = GetNamedGLImplementation(requested_implementation_name);
56 if (std::find(allowed_impls.begin(),
57 allowed_impls.end(),
58 impl) == allowed_impls.end()) {
59 LOG(ERROR) << "Requested GL implementation is not available.";
60 return false;
61 }
62 }
63 }
64
65 bool gpu_service_logging = cmd->HasSwitch(switches::kEnableGPUServiceLogging);
66 bool disable_gl_drawing = cmd->HasSwitch(switches::kDisableGLDrawingForTests);
67
68 return InitializeOneOffImplementation(
69 impl, fallback_to_osmesa, gpu_service_logging, disable_gl_drawing);
70 }
71
72 // static
InitializeOneOffImplementation(GLImplementation impl,bool fallback_to_osmesa,bool gpu_service_logging,bool disable_gl_drawing)73 bool GLSurface::InitializeOneOffImplementation(GLImplementation impl,
74 bool fallback_to_osmesa,
75 bool gpu_service_logging,
76 bool disable_gl_drawing) {
77 bool initialized =
78 InitializeStaticGLBindings(impl) && InitializeOneOffInternal();
79 if (!initialized && fallback_to_osmesa) {
80 ClearGLBindings();
81 initialized = InitializeStaticGLBindings(kGLImplementationOSMesaGL) &&
82 InitializeOneOffInternal();
83 }
84 if (!initialized)
85 ClearGLBindings();
86
87 if (initialized) {
88 DVLOG(1) << "Using "
89 << GetGLImplementationName(GetGLImplementation())
90 << " GL implementation.";
91 if (gpu_service_logging)
92 InitializeDebugGLBindings();
93 if (disable_gl_drawing)
94 InitializeNullDrawGLBindings();
95 }
96 return initialized;
97 }
98
99 // static
InitializeOneOffForTests()100 void GLSurface::InitializeOneOffForTests() {
101 DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
102
103 #if defined(USE_X11)
104 XInitThreads();
105 #endif
106
107 bool use_osmesa = true;
108
109 // We usually use OSMesa as this works on all bots. The command line can
110 // override this behaviour to use hardware GL.
111 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGpuInTests))
112 use_osmesa = false;
113
114 #if defined(OS_ANDROID)
115 // On Android we always use hardware GL.
116 use_osmesa = false;
117 #endif
118
119 std::vector<GLImplementation> allowed_impls;
120 GetAllowedGLImplementations(&allowed_impls);
121 DCHECK(!allowed_impls.empty());
122
123 GLImplementation impl = allowed_impls[0];
124 if (use_osmesa)
125 impl = kGLImplementationOSMesaGL;
126
127 DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL))
128 << "kUseGL has not effect in tests";
129
130 bool fallback_to_osmesa = false;
131 bool gpu_service_logging = false;
132 bool disable_gl_drawing = true;
133
134 CHECK(InitializeOneOffImplementation(
135 impl, fallback_to_osmesa, gpu_service_logging, disable_gl_drawing));
136 }
137
138 // static
InitializeOneOffWithMockBindingsForTests()139 void GLSurface::InitializeOneOffWithMockBindingsForTests() {
140 DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL))
141 << "kUseGL has not effect in tests";
142
143 // This method may be called multiple times in the same process to set up
144 // mock bindings in different ways.
145 ClearGLBindings();
146
147 bool fallback_to_osmesa = false;
148 bool gpu_service_logging = false;
149 bool disable_gl_drawing = false;
150
151 CHECK(InitializeOneOffImplementation(kGLImplementationMockGL,
152 fallback_to_osmesa,
153 gpu_service_logging,
154 disable_gl_drawing));
155 }
156
157 // static
InitializeDynamicMockBindingsForTests(GLContext * context)158 void GLSurface::InitializeDynamicMockBindingsForTests(GLContext* context) {
159 CHECK(InitializeDynamicGLBindings(kGLImplementationMockGL, context));
160 }
161
GLSurface()162 GLSurface::GLSurface() {}
163
Initialize()164 bool GLSurface::Initialize() {
165 return true;
166 }
167
Resize(const gfx::Size & size)168 bool GLSurface::Resize(const gfx::Size& size) {
169 NOTIMPLEMENTED();
170 return false;
171 }
172
Recreate()173 bool GLSurface::Recreate() {
174 NOTIMPLEMENTED();
175 return false;
176 }
177
DeferDraws()178 bool GLSurface::DeferDraws() {
179 return false;
180 }
181
SupportsPostSubBuffer()182 bool GLSurface::SupportsPostSubBuffer() {
183 return false;
184 }
185
GetBackingFrameBufferObject()186 unsigned int GLSurface::GetBackingFrameBufferObject() {
187 return 0;
188 }
189
PostSubBuffer(int x,int y,int width,int height)190 bool GLSurface::PostSubBuffer(int x, int y, int width, int height) {
191 return false;
192 }
193
OnMakeCurrent(GLContext * context)194 bool GLSurface::OnMakeCurrent(GLContext* context) {
195 return true;
196 }
197
SetBackbufferAllocation(bool allocated)198 bool GLSurface::SetBackbufferAllocation(bool allocated) {
199 return true;
200 }
201
SetFrontbufferAllocation(bool allocated)202 void GLSurface::SetFrontbufferAllocation(bool allocated) {
203 }
204
GetShareHandle()205 void* GLSurface::GetShareHandle() {
206 NOTIMPLEMENTED();
207 return NULL;
208 }
209
GetDisplay()210 void* GLSurface::GetDisplay() {
211 NOTIMPLEMENTED();
212 return NULL;
213 }
214
GetConfig()215 void* GLSurface::GetConfig() {
216 NOTIMPLEMENTED();
217 return NULL;
218 }
219
GetFormat()220 unsigned GLSurface::GetFormat() {
221 NOTIMPLEMENTED();
222 return 0;
223 }
224
GetVSyncProvider()225 VSyncProvider* GLSurface::GetVSyncProvider() {
226 return NULL;
227 }
228
ScheduleOverlayPlane(int z_order,OverlayTransform transform,GLImage * image,const Rect & bounds_rect,const RectF & crop_rect)229 bool GLSurface::ScheduleOverlayPlane(int z_order,
230 OverlayTransform transform,
231 GLImage* image,
232 const Rect& bounds_rect,
233 const RectF& crop_rect) {
234 NOTIMPLEMENTED();
235 return false;
236 }
237
IsSurfaceless() const238 bool GLSurface::IsSurfaceless() const {
239 return false;
240 }
241
GetCurrent()242 GLSurface* GLSurface::GetCurrent() {
243 return current_surface_.Pointer()->Get();
244 }
245
~GLSurface()246 GLSurface::~GLSurface() {
247 if (GetCurrent() == this)
248 SetCurrent(NULL);
249 }
250
SetCurrent(GLSurface * surface)251 void GLSurface::SetCurrent(GLSurface* surface) {
252 current_surface_.Pointer()->Set(surface);
253 }
254
ExtensionsContain(const char * c_extensions,const char * name)255 bool GLSurface::ExtensionsContain(const char* c_extensions, const char* name) {
256 DCHECK(name);
257 if (!c_extensions)
258 return false;
259 std::string extensions(c_extensions);
260 extensions += " ";
261
262 std::string delimited_name(name);
263 delimited_name += " ";
264
265 return extensions.find(delimited_name) != std::string::npos;
266 }
267
GLSurfaceAdapter(GLSurface * surface)268 GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) {}
269
Initialize()270 bool GLSurfaceAdapter::Initialize() {
271 return surface_->Initialize();
272 }
273
Destroy()274 void GLSurfaceAdapter::Destroy() {
275 surface_->Destroy();
276 }
277
Resize(const gfx::Size & size)278 bool GLSurfaceAdapter::Resize(const gfx::Size& size) {
279 return surface_->Resize(size);
280 }
281
Recreate()282 bool GLSurfaceAdapter::Recreate() {
283 return surface_->Recreate();
284 }
285
DeferDraws()286 bool GLSurfaceAdapter::DeferDraws() {
287 return surface_->DeferDraws();
288 }
289
IsOffscreen()290 bool GLSurfaceAdapter::IsOffscreen() {
291 return surface_->IsOffscreen();
292 }
293
SwapBuffers()294 bool GLSurfaceAdapter::SwapBuffers() {
295 return surface_->SwapBuffers();
296 }
297
PostSubBuffer(int x,int y,int width,int height)298 bool GLSurfaceAdapter::PostSubBuffer(int x, int y, int width, int height) {
299 return surface_->PostSubBuffer(x, y, width, height);
300 }
301
SupportsPostSubBuffer()302 bool GLSurfaceAdapter::SupportsPostSubBuffer() {
303 return surface_->SupportsPostSubBuffer();
304 }
305
GetSize()306 gfx::Size GLSurfaceAdapter::GetSize() {
307 return surface_->GetSize();
308 }
309
GetHandle()310 void* GLSurfaceAdapter::GetHandle() {
311 return surface_->GetHandle();
312 }
313
GetBackingFrameBufferObject()314 unsigned int GLSurfaceAdapter::GetBackingFrameBufferObject() {
315 return surface_->GetBackingFrameBufferObject();
316 }
317
OnMakeCurrent(GLContext * context)318 bool GLSurfaceAdapter::OnMakeCurrent(GLContext* context) {
319 return surface_->OnMakeCurrent(context);
320 }
321
SetBackbufferAllocation(bool allocated)322 bool GLSurfaceAdapter::SetBackbufferAllocation(bool allocated) {
323 return surface_->SetBackbufferAllocation(allocated);
324 }
325
SetFrontbufferAllocation(bool allocated)326 void GLSurfaceAdapter::SetFrontbufferAllocation(bool allocated) {
327 surface_->SetFrontbufferAllocation(allocated);
328 }
329
GetShareHandle()330 void* GLSurfaceAdapter::GetShareHandle() {
331 return surface_->GetShareHandle();
332 }
333
GetDisplay()334 void* GLSurfaceAdapter::GetDisplay() {
335 return surface_->GetDisplay();
336 }
337
GetConfig()338 void* GLSurfaceAdapter::GetConfig() {
339 return surface_->GetConfig();
340 }
341
GetFormat()342 unsigned GLSurfaceAdapter::GetFormat() {
343 return surface_->GetFormat();
344 }
345
GetVSyncProvider()346 VSyncProvider* GLSurfaceAdapter::GetVSyncProvider() {
347 return surface_->GetVSyncProvider();
348 }
349
ScheduleOverlayPlane(int z_order,OverlayTransform transform,GLImage * image,const Rect & bounds_rect,const RectF & crop_rect)350 bool GLSurfaceAdapter::ScheduleOverlayPlane(int z_order,
351 OverlayTransform transform,
352 GLImage* image,
353 const Rect& bounds_rect,
354 const RectF& crop_rect) {
355 return surface_->ScheduleOverlayPlane(
356 z_order, transform, image, bounds_rect, crop_rect);
357 }
358
IsSurfaceless() const359 bool GLSurfaceAdapter::IsSurfaceless() const {
360 return surface_->IsSurfaceless();
361 }
362
~GLSurfaceAdapter()363 GLSurfaceAdapter::~GLSurfaceAdapter() {}
364
365 } // namespace gfx
366