summaryrefslogtreecommitdiffstats
path: root/ui/gl/gl_image_memory.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ui/gl/gl_image_memory.cc')
-rw-r--r--ui/gl/gl_image_memory.cc200
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