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