15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/sys_info.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_egl.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/gl/gl_context_osmesa.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_stub.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/gl_surface.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to render into an already current context+surface,
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that we do not have ownership of (draw callback).
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// TODO(boliu): Make this inherit from GLContextEGL.
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class GLNonOwnedContext : public GLContextReal {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GLNonOwnedContext(GLShareGroup* share_group);
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Implement GLContext.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool Initialize(GLSurface* compatible_surface,
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                          GpuPreference gpu_preference) OVERRIDE;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Destroy() OVERRIDE {}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool MakeCurrent(GLSurface* surface) OVERRIDE;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE {}
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool IsCurrent(GLSurface* surface) OVERRIDE { return true; }
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void* GetHandle() OVERRIDE { return NULL; }
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetSwapInterval(int interval) OVERRIDE {}
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual std::string GetExtensions() OVERRIDE;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~GLNonOwnedContext() {}
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GLNonOwnedContext);
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EGLDisplay display_;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GLNonOwnedContext::GLNonOwnedContext(GLShareGroup* share_group)
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  : GLContextReal(share_group), display_(NULL) {}
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool GLNonOwnedContext::Initialize(GLSurface* compatible_surface,
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        GpuPreference gpu_preference) {
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return true;
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLNonOwnedContext::MakeCurrent(GLSurface* surface) {
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetCurrent(surface);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetRealGLApi();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GLNonOwnedContext::GetExtensions() {
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const char* extensions = eglQueryString(display_, EGL_EXTENSIONS);
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!extensions)
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return GLContext::GetExtensions();
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return GLContext::GetExtensions() + " " + extensions;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // anonymous namespace
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<GLContext> GLContext::CreateGLContext(
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLShareGroup* share_group,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLSurface* compatible_surface,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuPreference gpu_preference) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<GLContext> context;
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (GetGLImplementation()) {
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case kGLImplementationMockGL:
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return scoped_refptr<GLContext>(new GLContextStub());
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case kGLImplementationOSMesaGL:
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      context = new GLContextOSMesa(share_group);
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    default:
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (compatible_surface->GetHandle())
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        context = new GLContextEGL(share_group);
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      else
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        context = new GLNonOwnedContext(share_group);
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!context->Initialize(compatible_surface, gpu_preference))
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(bytes);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *bytes = 0;
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // We can't query available GPU memory from the system on Android.
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // 128MB java heap size). First we estimate physical memory using both.
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB();
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  size_t physical_memory_mb = 0;
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (dalvik_mb >= 256)
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    physical_memory_mb = dalvik_mb * 4;
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  else
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    physical_memory_mb = std::max(dalvik_mb * 4,
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  (physical_mb * 4) / 3);
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Now we take a default of 1/8th of memory on high-memory devices,
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // and gradually scale that back for low-memory devices (to be nicer
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // to other apps so they don't get killed). Examples:
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Nexus 4/10(2GB)    256MB (normally 128MB)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Droid Razr M(1GB)  114MB (normally 57MB)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Galaxy Nexus(1GB)  100MB (normally 50MB)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Xoom(1GB)          100MB (normally 50MB)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Nexus S(low-end)   12MB (normally 8MB)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Note that the compositor now uses only some of this memory for
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // pre-painting and uses the rest only for 'emergencies'.
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  static size_t limit_bytes = 0;
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (limit_bytes == 0) {
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // NOTE: Non-low-end devices use only 50% of these limits,
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // except during 'emergencies' where 100% can be used.
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!base::SysInfo::IsLowEndDevice()) {
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (physical_memory_mb >= 1536)
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        limit_bytes = physical_memory_mb / 8; // >192MB
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      else if (physical_memory_mb >= 1152)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        limit_bytes = physical_memory_mb / 8; // >144MB
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      else if (physical_memory_mb >= 768)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        limit_bytes = physical_memory_mb / 10; // >76MB
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      else
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        limit_bytes = physical_memory_mb / 12; // <64MB
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else {
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // Low-end devices have 512MB or less memory by definition
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // so we hard code the limit rather than relying on the heuristics
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // above. Low-end devices use 4444 textures so we can use a lower limit.
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // NOTE: Low-end uses 2/3 (67%) of this memory in practice, so we have
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // increased the limit to 12 (8MB, or 12MB in emergencies).
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      limit_bytes = 12;
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    limit_bytes = limit_bytes * 1024 * 1024;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  *bytes = limit_bytes;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
154