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_context.h"
6
7#include "base/logging.h"
8#include "base/memory/ref_counted.h"
9#include "base/sys_info.h"
10#include "ui/gl/gl_bindings.h"
11#include "ui/gl/gl_context_egl.h"
12#include "ui/gl/gl_context_osmesa.h"
13#include "ui/gl/gl_context_stub.h"
14#include "ui/gl/gl_implementation.h"
15#include "ui/gl/gl_surface.h"
16
17namespace gfx {
18
19namespace {
20
21// Used to render into an already current context+surface,
22// that we do not have ownership of (draw callback).
23// TODO(boliu): Make this inherit from GLContextEGL.
24class GLNonOwnedContext : public GLContextReal {
25 public:
26  GLNonOwnedContext(GLShareGroup* share_group);
27
28  // Implement GLContext.
29  virtual bool Initialize(GLSurface* compatible_surface,
30                          GpuPreference gpu_preference) OVERRIDE;
31  virtual void Destroy() OVERRIDE {}
32  virtual bool MakeCurrent(GLSurface* surface) OVERRIDE;
33  virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE {}
34  virtual bool IsCurrent(GLSurface* surface) OVERRIDE { return true; }
35  virtual void* GetHandle() OVERRIDE { return NULL; }
36  virtual void SetSwapInterval(int interval) OVERRIDE {}
37  virtual std::string GetExtensions() OVERRIDE;
38
39 protected:
40  virtual ~GLNonOwnedContext() {}
41
42 private:
43  DISALLOW_COPY_AND_ASSIGN(GLNonOwnedContext);
44
45  EGLDisplay display_;
46};
47
48GLNonOwnedContext::GLNonOwnedContext(GLShareGroup* share_group)
49  : GLContextReal(share_group), display_(NULL) {}
50
51bool GLNonOwnedContext::Initialize(GLSurface* compatible_surface,
52                        GpuPreference gpu_preference) {
53  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
54  return true;
55}
56
57bool GLNonOwnedContext::MakeCurrent(GLSurface* surface) {
58  SetCurrent(surface);
59  SetRealGLApi();
60  return true;
61}
62
63std::string GLNonOwnedContext::GetExtensions() {
64  const char* extensions = eglQueryString(display_, EGL_EXTENSIONS);
65  if (!extensions)
66    return GLContext::GetExtensions();
67
68  return GLContext::GetExtensions() + " " + extensions;
69}
70
71}  // anonymous namespace
72
73// static
74scoped_refptr<GLContext> GLContext::CreateGLContext(
75    GLShareGroup* share_group,
76    GLSurface* compatible_surface,
77    GpuPreference gpu_preference) {
78  scoped_refptr<GLContext> context;
79  switch (GetGLImplementation()) {
80    case kGLImplementationMockGL:
81      return scoped_refptr<GLContext>(new GLContextStub());
82    case kGLImplementationOSMesaGL:
83      context = new GLContextOSMesa(share_group);
84      break;
85    default:
86      if (compatible_surface->GetHandle())
87        context = new GLContextEGL(share_group);
88      else
89        context = new GLNonOwnedContext(share_group);
90      break;
91  }
92
93  if (!context->Initialize(compatible_surface, gpu_preference))
94    return NULL;
95
96  return context;
97}
98
99bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) {
100  DCHECK(bytes);
101  *bytes = 0;
102
103  // We can't query available GPU memory from the system on Android.
104  // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports
105  // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports
106  // 128MB java heap size). First we estimate physical memory using both.
107  size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB();
108  size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
109  size_t physical_memory_mb = 0;
110  if (dalvik_mb >= 256)
111    physical_memory_mb = dalvik_mb * 4;
112  else
113    physical_memory_mb = std::max(dalvik_mb * 4,
114                                  (physical_mb * 4) / 3);
115
116  // Now we take a default of 1/8th of memory on high-memory devices,
117  // and gradually scale that back for low-memory devices (to be nicer
118  // to other apps so they don't get killed). Examples:
119  // Nexus 4/10(2GB)    256MB (normally 128MB)
120  // Droid Razr M(1GB)  114MB (normally 57MB)
121  // Galaxy Nexus(1GB)  100MB (normally 50MB)
122  // Xoom(1GB)          100MB (normally 50MB)
123  // Nexus S(low-end)   12MB (normally 8MB)
124  // Note that the compositor now uses only some of this memory for
125  // pre-painting and uses the rest only for 'emergencies'.
126  static size_t limit_bytes = 0;
127  if (limit_bytes == 0) {
128    // NOTE: Non-low-end devices use only 50% of these limits,
129    // except during 'emergencies' where 100% can be used.
130    if (!base::SysInfo::IsLowEndDevice()) {
131      if (physical_memory_mb >= 1536)
132        limit_bytes = physical_memory_mb / 8; // >192MB
133      else if (physical_memory_mb >= 1152)
134        limit_bytes = physical_memory_mb / 8; // >144MB
135      else if (physical_memory_mb >= 768)
136        limit_bytes = physical_memory_mb / 10; // >76MB
137      else
138        limit_bytes = physical_memory_mb / 12; // <64MB
139    } else {
140      // Low-end devices have 512MB or less memory by definition
141      // so we hard code the limit rather than relying on the heuristics
142      // above. Low-end devices use 4444 textures so we can use a lower limit.
143      // NOTE: Low-end uses 2/3 (67%) of this memory in practice, so we have
144      // increased the limit to 12 (8MB, or 12MB in emergencies).
145      limit_bytes = 12;
146    }
147    limit_bytes = limit_bytes * 1024 * 1024;
148  }
149  *bytes = limit_bytes;
150  return true;
151}
152
153}
154