1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/gl/gl_image_shm.h"
7 #include "base/debug/trace_event.h"
8 #include "base/process/process_handle.h"
9 #include "ui/gl/scoped_binders.h"
11 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
13 #include "ui/gl/gl_surface_egl.h"
20 bool ValidFormat(unsigned internalformat) {
21 switch (internalformat) {
30 GLenum TextureFormat(unsigned internalformat) {
31 switch (internalformat) {
42 GLenum DataFormat(unsigned internalformat) {
43 return TextureFormat(internalformat);
46 GLenum DataType(unsigned internalformat) {
47 switch (internalformat) {
50 return GL_UNSIGNED_BYTE;
57 GLenum BytesPerPixel(unsigned internalformat) {
58 switch (internalformat) {
70 GLImageShm::GLImageShm(gfx::Size size, unsigned internalformat)
72 internalformat_(internalformat)
73 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
77 egl_image_(EGL_NO_IMAGE_KHR)
82 GLImageShm::~GLImageShm() { Destroy(); }
84 bool GLImageShm::Initialize(gfx::GpuMemoryBufferHandle buffer) {
85 if (!ValidFormat(internalformat_)) {
86 DVLOG(0) << "Invalid format: " << internalformat_;
90 if (!base::SharedMemory::IsHandleValid(buffer.handle))
93 base::SharedMemory shared_memory(buffer.handle, true);
95 // Duplicate the handle.
96 base::SharedMemoryHandle duped_shared_memory_handle;
97 if (!shared_memory.ShareToProcess(base::GetCurrentProcessHandle(),
98 &duped_shared_memory_handle)) {
99 DVLOG(0) << "Failed to duplicate shared memory handle.";
103 shared_memory_.reset(
104 new base::SharedMemory(duped_shared_memory_handle, true));
108 void GLImageShm::Destroy() {
109 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
111 if (egl_image_ != EGL_NO_IMAGE_KHR) {
112 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
113 egl_image_ = EGL_NO_IMAGE_KHR;
116 if (egl_texture_id_) {
117 glDeleteTextures(1, &egl_texture_id_);
118 egl_texture_id_ = 0u;
123 gfx::Size GLImageShm::GetSize() { return size_; }
125 bool GLImageShm::BindTexImage(unsigned target) {
126 TRACE_EVENT0("gpu", "GLImageShm::BindTexImage");
127 DCHECK(shared_memory_);
128 DCHECK(ValidFormat(internalformat_));
130 size_t size = size_.GetArea() * BytesPerPixel(internalformat_);
131 DCHECK(!shared_memory_->memory());
132 if (!shared_memory_->Map(size)) {
133 DVLOG(0) << "Failed to map shared memory.";
137 DCHECK(shared_memory_->memory());
139 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
141 if (target == GL_TEXTURE_EXTERNAL_OES) {
142 if (egl_image_ == EGL_NO_IMAGE_KHR) {
143 DCHECK_EQ(0u, egl_texture_id_);
144 glGenTextures(1, &egl_texture_id_);
147 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
149 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
152 glTexImage2D(GL_TEXTURE_2D,
154 TextureFormat(internalformat_),
158 DataFormat(internalformat_),
159 DataType(internalformat_),
160 shared_memory_->memory());
163 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
164 // Need to pass current EGL rendering context to eglCreateImageKHR for
165 // target type EGL_GL_TEXTURE_2D_KHR.
167 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
168 eglGetCurrentContext(),
169 EGL_GL_TEXTURE_2D_KHR,
170 reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
172 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
173 << "Error creating EGLImage: " << eglGetError();
175 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
177 glTexSubImage2D(GL_TEXTURE_2D,
183 DataFormat(internalformat_),
184 DataType(internalformat_),
185 shared_memory_->memory());
188 glEGLImageTargetTexture2DOES(target, egl_image_);
189 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
191 shared_memory_->Unmap();
196 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
199 TextureFormat(internalformat_),
203 DataFormat(internalformat_),
204 DataType(internalformat_),
205 shared_memory_->memory());
207 shared_memory_->Unmap();