Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / gl / gl_image_shm.cc
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.
4
5 #include "ui/gl/gl_image_shm.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/process/process_handle.h"
9 #include "ui/gl/scoped_binders.h"
10
11 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
12     defined(USE_OZONE)
13 #include "ui/gl/gl_surface_egl.h"
14 #endif
15
16 namespace gfx {
17
18 namespace {
19
20 bool ValidFormat(unsigned internalformat) {
21   switch (internalformat) {
22     case GL_BGRA8_EXT:
23     case GL_RGBA8_OES:
24       return true;
25     default:
26       return false;
27   }
28 }
29
30 GLenum TextureFormat(unsigned internalformat) {
31   switch (internalformat) {
32     case GL_BGRA8_EXT:
33       return GL_BGRA_EXT;
34     case GL_RGBA8_OES:
35       return GL_RGBA;
36     default:
37       NOTREACHED();
38       return 0;
39   }
40 }
41
42 GLenum DataFormat(unsigned internalformat) {
43   return TextureFormat(internalformat);
44 }
45
46 GLenum DataType(unsigned internalformat) {
47   switch (internalformat) {
48     case GL_BGRA8_EXT:
49     case GL_RGBA8_OES:
50       return GL_UNSIGNED_BYTE;
51     default:
52       NOTREACHED();
53       return 0;
54   }
55 }
56
57 GLenum BytesPerPixel(unsigned internalformat) {
58   switch (internalformat) {
59     case GL_BGRA8_EXT:
60     case GL_RGBA8_OES:
61       return 4;
62     default:
63       NOTREACHED();
64       return 0;
65   }
66 }
67
68 }  // namespace
69
70 GLImageShm::GLImageShm(gfx::Size size, unsigned internalformat)
71     : size_(size),
72       internalformat_(internalformat)
73 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
74     defined(USE_OZONE)
75       ,
76       egl_texture_id_(0u),
77       egl_image_(EGL_NO_IMAGE_KHR)
78 #endif
79 {
80 }
81
82 GLImageShm::~GLImageShm() { Destroy(); }
83
84 bool GLImageShm::Initialize(gfx::GpuMemoryBufferHandle buffer) {
85   if (!ValidFormat(internalformat_)) {
86     DVLOG(0) << "Invalid format: " << internalformat_;
87     return false;
88   }
89
90   if (!base::SharedMemory::IsHandleValid(buffer.handle))
91     return false;
92
93   base::SharedMemory shared_memory(buffer.handle, true);
94
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.";
100     return false;
101   }
102
103   shared_memory_.reset(
104       new base::SharedMemory(duped_shared_memory_handle, true));
105   return true;
106 }
107
108 void GLImageShm::Destroy() {
109 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
110     defined(USE_OZONE)
111   if (egl_image_ != EGL_NO_IMAGE_KHR) {
112     eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
113     egl_image_ = EGL_NO_IMAGE_KHR;
114   }
115
116   if (egl_texture_id_) {
117     glDeleteTextures(1, &egl_texture_id_);
118     egl_texture_id_ = 0u;
119   }
120 #endif
121 }
122
123 gfx::Size GLImageShm::GetSize() { return size_; }
124
125 bool GLImageShm::BindTexImage(unsigned target) {
126   TRACE_EVENT0("gpu", "GLImageShm::BindTexImage");
127   DCHECK(shared_memory_);
128   DCHECK(ValidFormat(internalformat_));
129
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.";
134     return false;
135   }
136
137   DCHECK(shared_memory_->memory());
138
139 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
140     defined(USE_OZONE)
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_);
145
146       {
147         ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
148
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,
153                      0,  // mip level
154                      TextureFormat(internalformat_),
155                      size_.width(),
156                      size_.height(),
157                      0,  // border
158                      DataFormat(internalformat_),
159                      DataType(internalformat_),
160                      shared_memory_->memory());
161       }
162
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.
166       egl_image_ =
167           eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
168                             eglGetCurrentContext(),
169                             EGL_GL_TEXTURE_2D_KHR,
170                             reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
171                             attrs);
172       DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
173           << "Error creating EGLImage: " << eglGetError();
174     } else {
175       ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
176
177       glTexSubImage2D(GL_TEXTURE_2D,
178                       0,  // mip level
179                       0,  // x-offset
180                       0,  // y-offset
181                       size_.width(),
182                       size_.height(),
183                       DataFormat(internalformat_),
184                       DataType(internalformat_),
185                       shared_memory_->memory());
186     }
187
188     glEGLImageTargetTexture2DOES(target, egl_image_);
189     DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
190
191     shared_memory_->Unmap();
192     return true;
193   }
194 #endif
195
196   DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
197   glTexImage2D(target,
198                0,  // mip level
199                TextureFormat(internalformat_),
200                size_.width(),
201                size_.height(),
202                0,  // border
203                DataFormat(internalformat_),
204                DataType(internalformat_),
205                shared_memory_->memory());
206
207   shared_memory_->Unmap();
208   return true;
209 }
210
211 }  // namespace gfx