blob: 9d3c86cf4b5cfa6ea258c18c50ea803f3b2b4aa5 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gl/gl_context.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/sys_info.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context_egl.h"
#include "ui/gl/gl_context_osmesa.h"
#include "ui/gl/gl_context_stub.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
namespace gfx {
namespace {
// Used to render into an already current context+surface,
// that we do not have ownership of (draw callback).
// TODO(boliu): Make this inherit from GLContextEGL.
class GLNonOwnedContext : public GLContextReal {
public:
GLNonOwnedContext(GLShareGroup* share_group);
// Implement GLContext.
bool Initialize(GLSurface* compatible_surface,
GpuPreference gpu_preference) override;
void Destroy() override {}
bool MakeCurrent(GLSurface* surface) override;
void ReleaseCurrent(GLSurface* surface) override {}
bool IsCurrent(GLSurface* surface) override { return true; }
void* GetHandle() override { return NULL; }
void OnSetSwapInterval(int interval) override {}
std::string GetExtensions() override;
protected:
~GLNonOwnedContext() override {}
private:
DISALLOW_COPY_AND_ASSIGN(GLNonOwnedContext);
EGLDisplay display_;
};
GLNonOwnedContext::GLNonOwnedContext(GLShareGroup* share_group)
: GLContextReal(share_group), display_(NULL) {}
bool GLNonOwnedContext::Initialize(GLSurface* compatible_surface,
GpuPreference gpu_preference) {
display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
return true;
}
bool GLNonOwnedContext::MakeCurrent(GLSurface* surface) {
SetCurrent(surface);
SetRealGLApi();
return true;
}
std::string GLNonOwnedContext::GetExtensions() {
const char* extensions = eglQueryString(display_, EGL_EXTENSIONS);
if (!extensions)
return GLContext::GetExtensions();
return GLContext::GetExtensions() + " " + extensions;
}
} // anonymous namespace
// static
scoped_refptr<GLContext> GLContext::CreateGLContext(
GLShareGroup* share_group,
GLSurface* compatible_surface,
GpuPreference gpu_preference) {
scoped_refptr<GLContext> context;
switch (GetGLImplementation()) {
case kGLImplementationMockGL:
return scoped_refptr<GLContext>(new GLContextStub());
case kGLImplementationOSMesaGL:
context = new GLContextOSMesa(share_group);
break;
default:
if (compatible_surface->GetHandle())
context = new GLContextEGL(share_group);
else
context = new GLNonOwnedContext(share_group);
break;
}
if (!context->Initialize(compatible_surface, gpu_preference))
return NULL;
return context;
}
bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) {
DCHECK(bytes);
*bytes = 0;
// We can't query available GPU memory from the system on Android.
// Physical memory is also mis-reported sometimes (eg. Nexus 10 reports
// 1262MB when it actually has 2GB, while Razr M has 1GB but only reports
// 128MB java heap size). First we estimate physical memory using both.
size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB();
size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
size_t physical_memory_mb = 0;
if (dalvik_mb >= 256)
physical_memory_mb = dalvik_mb * 4;
else
physical_memory_mb = std::max(dalvik_mb * 4,
(physical_mb * 4) / 3);
// Now we take a default of 1/8th of memory on high-memory devices,
// and gradually scale that back for low-memory devices (to be nicer
// to other apps so they don't get killed). Examples:
// Nexus 4/10(2GB) 256MB (normally 128MB)
// Droid Razr M(1GB) 114MB (normally 57MB)
// Galaxy Nexus(1GB) 100MB (normally 50MB)
// Xoom(1GB) 100MB (normally 50MB)
// Nexus S(low-end) 8MB (normally 8MB)
// Note that the compositor now uses only some of this memory for
// pre-painting and uses the rest only for 'emergencies'.
static size_t limit_bytes = 0;
if (limit_bytes == 0) {
// NOTE: Non-low-end devices use only 50% of these limits,
// except during 'emergencies' where 100% can be used.
if (!base::SysInfo::IsLowEndDevice()) {
if (physical_memory_mb >= 1536)
limit_bytes = physical_memory_mb / 8; // >192MB
else if (physical_memory_mb >= 1152)
limit_bytes = physical_memory_mb / 8; // >144MB
else if (physical_memory_mb >= 768)
limit_bytes = physical_memory_mb / 10; // >76MB
else
limit_bytes = physical_memory_mb / 12; // <64MB
} else {
// Low-end devices have 512MB or less memory by definition
// so we hard code the limit rather than relying on the heuristics
// above. Low-end devices use 4444 textures so we can use a lower limit.
limit_bytes = 8;
}
limit_bytes = limit_bytes * 1024 * 1024;
}
*bytes = limit_bytes;
return true;
}
}