diff options
Diffstat (limited to 'ui/gl/gl_image_memory.cc')
-rw-r--r-- | ui/gl/gl_image_memory.cc | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc new file mode 100644 index 0000000..5d0f901 --- /dev/null +++ b/ui/gl/gl_image_memory.cc @@ -0,0 +1,200 @@ +// Copyright 2014 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_image_memory.h" + +#include "base/debug/trace_event.h" +#include "base/logging.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/scoped_binders.h" + +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) +#include "ui/gl/gl_surface_egl.h" +#endif + +namespace gfx { +namespace { + +bool ValidFormat(unsigned internalformat) { + switch (internalformat) { + case GL_BGRA8_EXT: + case GL_RGBA8_OES: + return true; + default: + return false; + } +} + +GLenum TextureFormat(unsigned internalformat) { + switch (internalformat) { + case GL_BGRA8_EXT: + return GL_BGRA_EXT; + case GL_RGBA8_OES: + return GL_RGBA; + default: + NOTREACHED(); + return 0; + } +} + +GLenum DataFormat(unsigned internalformat) { + return TextureFormat(internalformat); +} + +GLenum DataType(unsigned internalformat) { + switch (internalformat) { + case GL_BGRA8_EXT: + case GL_RGBA8_OES: + return GL_UNSIGNED_BYTE; + default: + NOTREACHED(); + return 0; + } +} + +int BytesPerPixel(unsigned internalformat) { + switch (internalformat) { + case GL_BGRA8_EXT: + case GL_RGBA8_OES: + return 4; + default: + NOTREACHED(); + return 0; + } +} + +} // namespace + +GLImageMemory::GLImageMemory(const gfx::Size& size, unsigned internalformat) + : memory_(NULL), + size_(size), + internalformat_(internalformat) +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + , + egl_texture_id_(0u), + egl_image_(EGL_NO_IMAGE_KHR) +#endif +{ +} + +GLImageMemory::~GLImageMemory() { +} + +bool GLImageMemory::Initialize(const unsigned char* memory) { + if (!ValidFormat(internalformat_)) { + DVLOG(0) << "Invalid format: " << internalformat_; + return false; + } + + DCHECK(memory); + DCHECK(!memory_); + memory_ = memory; + return true; +} + +void GLImageMemory::Destroy() { +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + if (egl_image_ != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); + egl_image_ = EGL_NO_IMAGE_KHR; + } + + if (egl_texture_id_) { + glDeleteTextures(1, &egl_texture_id_); + egl_texture_id_ = 0u; + } +#endif + memory_ = NULL; +} + +gfx::Size GLImageMemory::GetSize() { + return size_; +} + +bool GLImageMemory::BindTexImage(unsigned target) { + TRACE_EVENT0("gpu", "GLImageMemory::BindTexImage"); + + DCHECK(memory_); +#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ + defined(USE_OZONE) + if (target == GL_TEXTURE_EXTERNAL_OES) { + if (egl_image_ == EGL_NO_IMAGE_KHR) { + DCHECK_EQ(0u, egl_texture_id_); + glGenTextures(1, &egl_texture_id_); + + { + ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, + 0, // mip level + TextureFormat(internalformat_), + size_.width(), + size_.height(), + 0, // border + DataFormat(internalformat_), + DataType(internalformat_), + memory_); + } + + EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; + // Need to pass current EGL rendering context to eglCreateImageKHR for + // target type EGL_GL_TEXTURE_2D_KHR. + egl_image_ = + eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), + eglGetCurrentContext(), + EGL_GL_TEXTURE_2D_KHR, + reinterpret_cast<EGLClientBuffer>(egl_texture_id_), + attrs); + DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) + << "Error creating EGLImage: " << eglGetError(); + } else { + ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); + + glTexSubImage2D(GL_TEXTURE_2D, + 0, // mip level + 0, // x-offset + 0, // y-offset + size_.width(), + size_.height(), + DataFormat(internalformat_), + DataType(internalformat_), + memory_); + } + + glEGLImageTargetTexture2DOES(target, egl_image_); + DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + return true; + } +#endif + + DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); + glTexImage2D(target, + 0, // mip level + TextureFormat(internalformat_), + size_.width(), + size_.height(), + 0, // border + DataFormat(internalformat_), + DataType(internalformat_), + memory_); + + return true; +} + +bool GLImageMemory::HasValidFormat() const { + return ValidFormat(internalformat_); +} + +size_t GLImageMemory::Bytes() const { + return size_.GetArea() * BytesPerPixel(internalformat_); +} + +} // namespace gfx |