Commit d0d54f5a authored by reveman@chromium.org's avatar reveman@chromium.org

ui: Refactor GLImageEGL for usage by targets other than EGL_NATIVE_BUFFER_ANDROID.

No changes in behavior except a DCHECK will fail in BindTexImage
instead of returning false when egl_image_ is EGL_NO_IMAGE_KHR.
This is more appropritate as only a bug in the implementation of
GLImageEGL can cause this to happen.

BUG=356871
TBR=sky

Review URL: https://codereview.chromium.org/212933009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260194 0039d316-1c4b-4281-b951-d872f2087c98
parent 30191535
...@@ -62,7 +62,7 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer { ...@@ -62,7 +62,7 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
} }
virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE { virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE {
gfx::GpuMemoryBufferHandle handle; gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::EGL_CLIENT_BUFFER; handle.type = gfx::ANDROID_NATIVE_BUFFER;
handle.native_buffer = g_gl_draw_functions->get_native_buffer(buffer_id_); handle.native_buffer = g_gl_draw_functions->get_native_buffer(buffer_id_);
return handle; return handle;
} }
......
...@@ -18,7 +18,7 @@ namespace gfx { ...@@ -18,7 +18,7 @@ namespace gfx {
enum GpuMemoryBufferType { enum GpuMemoryBufferType {
EMPTY_BUFFER, EMPTY_BUFFER,
SHARED_MEMORY_BUFFER, SHARED_MEMORY_BUFFER,
EGL_CLIENT_BUFFER, ANDROID_NATIVE_BUFFER,
IO_SURFACE_BUFFER, IO_SURFACE_BUFFER,
GPU_MEMORY_BUFFER_TYPE_LAST = IO_SURFACE_BUFFER GPU_MEMORY_BUFFER_TYPE_LAST = IO_SURFACE_BUFFER
}; };
......
...@@ -177,6 +177,8 @@ ...@@ -177,6 +177,8 @@
'egl_util.h', 'egl_util.h',
'gl_context_egl.cc', 'gl_context_egl.cc',
'gl_context_egl.h', 'gl_context_egl.h',
'gl_image_egl.cc',
'gl_image_egl.h',
'gl_surface_egl.cc', 'gl_surface_egl.cc',
'gl_surface_egl.h', 'gl_surface_egl.h',
'gl_egl_api_implementation.cc', 'gl_egl_api_implementation.cc',
...@@ -275,8 +277,8 @@ ...@@ -275,8 +277,8 @@
'gl_jni_headers', 'gl_jni_headers',
], ],
'sources': [ 'sources': [
'gl_image_egl.cc', 'gl_image_android_native_buffer.cc',
'gl_image_egl.h', 'gl_image_android_native_buffer.h',
], ],
'link_settings': { 'link_settings': {
'libraries': [ 'libraries': [
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include "ui/gl/gl_image.h" #include "ui/gl/gl_image.h"
#include "base/debug/trace_event.h" #include "base/debug/trace_event.h"
#include "ui/gl/gl_image_egl.h" #include "ui/gl/gl_image_android_native_buffer.h"
#include "ui/gl/gl_image_shm.h" #include "ui/gl/gl_image_shm.h"
#include "ui/gl/gl_image_stub.h" #include "ui/gl/gl_image_stub.h"
#include "ui/gl/gl_implementation.h" #include "ui/gl/gl_implementation.h"
...@@ -41,8 +41,9 @@ scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer( ...@@ -41,8 +41,9 @@ scoped_refptr<GLImage> GLImage::CreateGLImageForGpuMemoryBuffer(
return image; return image;
} }
case EGL_CLIENT_BUFFER: { case ANDROID_NATIVE_BUFFER: {
scoped_refptr<GLImageEGL> image(new GLImageEGL(size)); scoped_refptr<GLImageAndroidNativeBuffer> image(
new GLImageAndroidNativeBuffer(size));
if (!image->Initialize(buffer)) if (!image->Initialize(buffer))
return NULL; return NULL;
......
// 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_android_native_buffer.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/scoped_binders.h"
namespace gfx {
GLImageAndroidNativeBuffer::GLImageAndroidNativeBuffer(gfx::Size size)
: GLImageEGL(size),
release_after_use_(false),
in_use_(false),
target_(0),
egl_image_for_unbind_(EGL_NO_IMAGE_KHR),
texture_id_for_unbind_(0) {}
GLImageAndroidNativeBuffer::~GLImageAndroidNativeBuffer() { Destroy(); }
bool GLImageAndroidNativeBuffer::Initialize(gfx::GpuMemoryBufferHandle buffer) {
DCHECK(buffer.native_buffer);
EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
return GLImageEGL::Initialize(
EGL_NATIVE_BUFFER_ANDROID, buffer.native_buffer, attrs);
}
void GLImageAndroidNativeBuffer::Destroy() {
if (egl_image_for_unbind_ != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
egl_image_for_unbind_);
egl_image_for_unbind_ = EGL_NO_IMAGE_KHR;
}
if (texture_id_for_unbind_) {
glDeleteTextures(1, &texture_id_for_unbind_);
texture_id_for_unbind_ = 0;
}
GLImageEGL::Destroy();
}
bool GLImageAndroidNativeBuffer::BindTexImage(unsigned target) {
DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_);
if (target == GL_TEXTURE_RECTANGLE_ARB) {
LOG(ERROR) << "EGLImage cannot be bound to TEXTURE_RECTANGLE_ARB target";
return false;
}
if (target_ && target_ != target) {
LOG(ERROR) << "EGLImage can only be bound to one target";
return false;
}
target_ = target;
// Defer ImageTargetTexture2D if not currently in use.
if (!in_use_)
return true;
glEGLImageTargetTexture2DOES(target_, egl_image_);
DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
return true;
}
void GLImageAndroidNativeBuffer::WillUseTexImage() {
DCHECK(egl_image_);
DCHECK(!in_use_);
in_use_ = true;
glEGLImageTargetTexture2DOES(target_, egl_image_);
DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
}
void GLImageAndroidNativeBuffer::DidUseTexImage() {
DCHECK(in_use_);
in_use_ = false;
if (!release_after_use_)
return;
if (egl_image_for_unbind_ == EGL_NO_IMAGE_KHR) {
DCHECK_EQ(0u, texture_id_for_unbind_);
glGenTextures(1, &texture_id_for_unbind_);
{
ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_for_unbind_);
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);
char zero[4] = {0, };
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &zero);
}
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_for_unbind_ = eglCreateImageKHR(
GLSurfaceEGL::GetHardwareDisplay(),
eglGetCurrentContext(),
EGL_GL_TEXTURE_2D_KHR,
reinterpret_cast<EGLClientBuffer>(texture_id_for_unbind_),
attrs);
DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_for_unbind_)
<< "Error creating EGLImage: " << eglGetError();
}
glEGLImageTargetTexture2DOES(target_, egl_image_for_unbind_);
DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
}
void GLImageAndroidNativeBuffer::SetReleaseAfterUse() {
release_after_use_ = true;
}
} // namespace gfx
// 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.
#ifndef UI_GL_GL_IMAGE_ANDROID_NATIVE_BUFFER_H_
#define UI_GL_GL_IMAGE_ANDROID_NATIVE_BUFFER_H_
#include "ui/gl/gl_image_egl.h"
namespace gfx {
class GL_EXPORT GLImageAndroidNativeBuffer : public GLImageEGL {
public:
explicit GLImageAndroidNativeBuffer(gfx::Size size);
bool Initialize(gfx::GpuMemoryBufferHandle buffer);
// Overridden from GLImage:
virtual void Destroy() OVERRIDE;
virtual bool BindTexImage(unsigned target) OVERRIDE;
virtual void WillUseTexImage() OVERRIDE;
virtual void DidUseTexImage() OVERRIDE;
virtual void SetReleaseAfterUse() OVERRIDE;
protected:
virtual ~GLImageAndroidNativeBuffer();
private:
bool release_after_use_;
bool in_use_;
unsigned target_;
EGLImageKHR egl_image_for_unbind_;
GLuint texture_id_for_unbind_;
DISALLOW_COPY_AND_ASSIGN(GLImageAndroidNativeBuffer);
};
} // namespace gfx
#endif // UI_GL_GL_IMAGE_ANDROID_NATIVE_BUFFER_H_
...@@ -4,31 +4,23 @@ ...@@ -4,31 +4,23 @@
#include "ui/gl/gl_image_egl.h" #include "ui/gl/gl_image_egl.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_surface_egl.h" #include "ui/gl/gl_surface_egl.h"
#include "ui/gl/scoped_binders.h"
namespace gfx { namespace gfx {
GLImageEGL::GLImageEGL(gfx::Size size) GLImageEGL::GLImageEGL(gfx::Size size)
: egl_image_(EGL_NO_IMAGE_KHR), : egl_image_(EGL_NO_IMAGE_KHR), size_(size) {}
size_(size),
release_after_use_(false),
in_use_(false),
target_(0),
egl_image_for_unbind_(EGL_NO_IMAGE_KHR),
texture_id_for_unbind_(0) {}
GLImageEGL::~GLImageEGL() { Destroy(); } GLImageEGL::~GLImageEGL() { Destroy(); }
bool GLImageEGL::Initialize(gfx::GpuMemoryBufferHandle buffer) { bool GLImageEGL::Initialize(EGLenum target,
DCHECK(buffer.native_buffer); EGLClientBuffer buffer,
const EGLint* attrs) {
EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_);
egl_image_ = eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_ = eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
EGL_NO_CONTEXT, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, target,
buffer.native_buffer, buffer,
attrs); attrs);
if (egl_image_ == EGL_NO_IMAGE_KHR) { if (egl_image_ == EGL_NO_IMAGE_KHR) {
EGLint error = eglGetError(); EGLint error = eglGetError();
...@@ -44,100 +36,15 @@ void GLImageEGL::Destroy() { ...@@ -44,100 +36,15 @@ void GLImageEGL::Destroy() {
eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
egl_image_ = EGL_NO_IMAGE_KHR; egl_image_ = EGL_NO_IMAGE_KHR;
} }
if (egl_image_for_unbind_ != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
egl_image_for_unbind_);
egl_image_for_unbind_ = EGL_NO_IMAGE_KHR;
}
if (texture_id_for_unbind_) {
glDeleteTextures(1, &texture_id_for_unbind_);
texture_id_for_unbind_ = 0;
}
} }
gfx::Size GLImageEGL::GetSize() { return size_; } gfx::Size GLImageEGL::GetSize() { return size_; }
bool GLImageEGL::BindTexImage(unsigned target) { bool GLImageEGL::BindTexImage(unsigned target) {
if (egl_image_ == EGL_NO_IMAGE_KHR) { DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_);
LOG(ERROR) << "NULL EGLImage in BindTexImage"; glEGLImageTargetTexture2DOES(target, egl_image_);
return false;
}
if (target == GL_TEXTURE_RECTANGLE_ARB) {
LOG(ERROR) << "EGLImage cannot be bound to TEXTURE_RECTANGLE_ARB target";
return false;
}
if (target_ && target_ != target) {
LOG(ERROR) << "EGLImage can only be bound to one target";
return false;
}
target_ = target;
// Defer ImageTargetTexture2D if not currently in use.
if (!in_use_)
return true;
glEGLImageTargetTexture2DOES(target_, egl_image_);
DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
return true; return true;
} }
void GLImageEGL::ReleaseTexImage(unsigned target) {
// Nothing to do here as image is released after each use or there is no need
// to release image.
}
void GLImageEGL::WillUseTexImage() {
DCHECK(egl_image_);
DCHECK(!in_use_);
in_use_ = true;
glEGLImageTargetTexture2DOES(target_, egl_image_);
DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
}
void GLImageEGL::DidUseTexImage() {
DCHECK(in_use_);
in_use_ = false;
if (!release_after_use_)
return;
if (egl_image_for_unbind_ == EGL_NO_IMAGE_KHR) {
DCHECK_EQ(0u, texture_id_for_unbind_);
glGenTextures(1, &texture_id_for_unbind_);
{
ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_for_unbind_);
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);
char zero[4] = {0, };
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &zero);
}
EGLint attrs[] = {EGL_GL_TEXTURE_LEVEL_KHR, 0, 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_for_unbind_ = eglCreateImageKHR(
GLSurfaceEGL::GetHardwareDisplay(),
eglGetCurrentContext(),
EGL_GL_TEXTURE_2D_KHR,
reinterpret_cast<EGLClientBuffer>(texture_id_for_unbind_),
attrs);
DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_for_unbind_)
<< "Error creating EGLImage: " << eglGetError();
}
glEGLImageTargetTexture2DOES(target_, egl_image_for_unbind_);
DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
}
void GLImageEGL::SetReleaseAfterUse() { release_after_use_ = true; }
} // namespace gfx } // namespace gfx
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef UI_GL_GL_IMAGE_EGL_H_ #ifndef UI_GL_GL_IMAGE_EGL_H_
#define UI_GL_GL_IMAGE_EGL_H_ #define UI_GL_GL_IMAGE_EGL_H_
#include "ui/gl/gl_bindings.h" // for EGLImageKHR #include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image.h" #include "ui/gl/gl_image.h"
namespace gfx { namespace gfx {
...@@ -14,31 +14,25 @@ class GL_EXPORT GLImageEGL : public GLImage { ...@@ -14,31 +14,25 @@ class GL_EXPORT GLImageEGL : public GLImage {
public: public:
explicit GLImageEGL(gfx::Size size); explicit GLImageEGL(gfx::Size size);
bool Initialize(gfx::GpuMemoryBufferHandle buffer); bool Initialize(EGLenum target, EGLClientBuffer buffer, const EGLint* attrs);
// Overridden from GLImage: // Overridden from GLImage:
virtual void Destroy() OVERRIDE; virtual void Destroy() OVERRIDE;
virtual gfx::Size GetSize() OVERRIDE; virtual gfx::Size GetSize() OVERRIDE;
virtual bool BindTexImage(unsigned target) OVERRIDE; virtual bool BindTexImage(unsigned target) OVERRIDE;
virtual void ReleaseTexImage(unsigned target) OVERRIDE; virtual void ReleaseTexImage(unsigned target) OVERRIDE {}
virtual void WillUseTexImage() OVERRIDE; virtual void WillUseTexImage() OVERRIDE {}
virtual void DidUseTexImage() OVERRIDE; virtual void DidUseTexImage() OVERRIDE {}
virtual void WillModifyTexImage() OVERRIDE {} virtual void WillModifyTexImage() OVERRIDE {}
virtual void DidModifyTexImage() OVERRIDE {} virtual void DidModifyTexImage() OVERRIDE {}
virtual void SetReleaseAfterUse() OVERRIDE;
protected: protected:
virtual ~GLImageEGL(); virtual ~GLImageEGL();
private:
EGLImageKHR egl_image_; EGLImageKHR egl_image_;
gfx::Size size_; gfx::Size size_;
bool release_after_use_;
bool in_use_;
unsigned target_;
EGLImageKHR egl_image_for_unbind_;
GLuint texture_id_for_unbind_;
private:
DISALLOW_COPY_AND_ASSIGN(GLImageEGL); DISALLOW_COPY_AND_ASSIGN(GLImageEGL);
}; };
......
...@@ -162,8 +162,7 @@ bool GLImageShm::BindTexImage(unsigned target) { ...@@ -162,8 +162,7 @@ bool GLImageShm::BindTexImage(unsigned target) {
shared_memory_->memory()); shared_memory_->memory());
} }
EGLint attrs[] = {EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
EGL_TRUE, EGL_NONE};
// Need to pass current EGL rendering context to eglCreateImageKHR for // Need to pass current EGL rendering context to eglCreateImageKHR for
// target type EGL_GL_TEXTURE_2D_KHR. // target type EGL_GL_TEXTURE_2D_KHR.
egl_image_ = egl_image_ =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment