Upstream version 6.35.121.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       eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
144
145     if (!egl_texture_id_)
146       glGenTextures(1, &egl_texture_id_);
147
148     {
149       ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
150       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
151       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
152       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
153
154       glTexImage2D(GL_TEXTURE_2D,
155                    0,  // mip level
156                    TextureFormat(internalformat_),
157                    size_.width(),
158                    size_.height(),
159                    0,  // border
160                    DataFormat(internalformat_),
161                    DataType(internalformat_),
162                    shared_memory_->memory());
163     }
164
165     EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
166     // Need to pass current EGL rendering context to eglCreateImageKHR for
167     // target type EGL_GL_TEXTURE_2D_KHR.
168     egl_image_ =
169         eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
170                           eglGetCurrentContext(),
171                           EGL_GL_TEXTURE_2D_KHR,
172                           reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
173                           attrs);
174     DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
175         << "Error creating EGLImage: " << eglGetError();
176
177     glEGLImageTargetTexture2DOES(target, egl_image_);
178     DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
179
180     shared_memory_->Unmap();
181     return true;
182   }
183 #endif
184
185   DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
186   glTexImage2D(target,
187                0,  // mip level
188                TextureFormat(internalformat_),
189                size_.width(),
190                size_.height(),
191                0,  // border
192                DataFormat(internalformat_),
193                DataType(internalformat_),
194                shared_memory_->memory());
195
196   shared_memory_->Unmap();
197   return true;
198 }
199
200 }  // namespace gfx