Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / gl / gl_image_memory.cc
1 // Copyright 2014 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_memory.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "ui/gl/gl_bindings.h"
10 #include "ui/gl/scoped_binders.h"
11
12 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
13     defined(USE_OZONE)
14 #include "ui/gl/gl_surface_egl.h"
15 #endif
16
17 namespace gfx {
18 namespace {
19
20 bool ValidInternalFormat(unsigned internalformat) {
21   switch (internalformat) {
22     case GL_RGBA:
23       return true;
24     default:
25       return false;
26   }
27 }
28
29 bool ValidFormat(gfx::GpuMemoryBuffer::Format format) {
30   switch (format) {
31     case gfx::GpuMemoryBuffer::RGBA_8888:
32     case gfx::GpuMemoryBuffer::BGRA_8888:
33       return true;
34     case gfx::GpuMemoryBuffer::RGBX_8888:
35       return false;
36   }
37
38   NOTREACHED();
39   return false;
40 }
41
42 GLenum TextureFormat(gfx::GpuMemoryBuffer::Format format) {
43   switch (format) {
44     case gfx::GpuMemoryBuffer::RGBA_8888:
45       return GL_RGBA;
46     case gfx::GpuMemoryBuffer::BGRA_8888:
47       return GL_BGRA_EXT;
48     case gfx::GpuMemoryBuffer::RGBX_8888:
49       NOTREACHED();
50       return 0;
51   }
52
53   NOTREACHED();
54   return 0;
55 }
56
57 GLenum DataFormat(gfx::GpuMemoryBuffer::Format format) {
58   return TextureFormat(format);
59 }
60
61 GLenum DataType(gfx::GpuMemoryBuffer::Format format) {
62   switch (format) {
63     case gfx::GpuMemoryBuffer::RGBA_8888:
64     case gfx::GpuMemoryBuffer::BGRA_8888:
65       return GL_UNSIGNED_BYTE;
66     case gfx::GpuMemoryBuffer::RGBX_8888:
67       NOTREACHED();
68       return 0;
69   }
70
71   NOTREACHED();
72   return 0;
73 }
74
75 }  // namespace
76
77 GLImageMemory::GLImageMemory(const gfx::Size& size, unsigned internalformat)
78     : size_(size),
79       internalformat_(internalformat),
80       memory_(NULL),
81       format_(gfx::GpuMemoryBuffer::RGBA_8888),
82       in_use_(false),
83       target_(0),
84       need_do_bind_tex_image_(false)
85 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
86     defined(USE_OZONE)
87       ,
88       egl_texture_id_(0u),
89       egl_image_(EGL_NO_IMAGE_KHR)
90 #endif
91 {
92 }
93
94 GLImageMemory::~GLImageMemory() {
95 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
96     defined(USE_OZONE)
97   DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_);
98   DCHECK_EQ(0u, egl_texture_id_);
99 #endif
100 }
101
102 // static
103 size_t GLImageMemory::BytesPerPixel(gfx::GpuMemoryBuffer::Format format) {
104   switch (format) {
105     case gfx::GpuMemoryBuffer::RGBA_8888:
106     case gfx::GpuMemoryBuffer::BGRA_8888:
107       return 4;
108     case gfx::GpuMemoryBuffer::RGBX_8888:
109       NOTREACHED();
110       return 0;
111   }
112
113   NOTREACHED();
114   return 0;
115 }
116
117 bool GLImageMemory::Initialize(const unsigned char* memory,
118                                gfx::GpuMemoryBuffer::Format format) {
119   if (!ValidInternalFormat(internalformat_)) {
120     LOG(ERROR) << "Invalid internalformat: " << internalformat_;
121     return false;
122   }
123
124   if (!ValidFormat(format)) {
125     LOG(ERROR) << "Invalid format: " << format;
126     return false;
127   }
128
129   DCHECK(memory);
130   DCHECK(!memory_);
131   memory_ = memory;
132   format_ = format;
133   return true;
134 }
135
136 void GLImageMemory::Destroy(bool have_context) {
137 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
138     defined(USE_OZONE)
139   if (egl_image_ != EGL_NO_IMAGE_KHR) {
140     eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
141     egl_image_ = EGL_NO_IMAGE_KHR;
142   }
143
144   if (egl_texture_id_) {
145     if (have_context)
146       glDeleteTextures(1, &egl_texture_id_);
147     egl_texture_id_ = 0u;
148   }
149 #endif
150   memory_ = NULL;
151 }
152
153 gfx::Size GLImageMemory::GetSize() {
154   return size_;
155 }
156
157 bool GLImageMemory::BindTexImage(unsigned target) {
158   if (target_ && target_ != target) {
159     LOG(ERROR) << "GLImage can only be bound to one target";
160     return false;
161   }
162   target_ = target;
163
164   // Defer DoBindTexImage if not currently in use.
165   if (!in_use_) {
166     need_do_bind_tex_image_ = true;
167     return true;
168   }
169
170   DoBindTexImage(target);
171   return true;
172 }
173
174 bool GLImageMemory::CopyTexImage(unsigned target) {
175   TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage");
176
177   // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target.
178   if (target == GL_TEXTURE_EXTERNAL_OES)
179     return false;
180
181   DCHECK(memory_);
182   glTexImage2D(target,
183                0,  // mip level
184                TextureFormat(format_),
185                size_.width(),
186                size_.height(),
187                0,  // border
188                DataFormat(format_),
189                DataType(format_),
190                memory_);
191
192   return true;
193 }
194
195 void GLImageMemory::WillUseTexImage() {
196   DCHECK(!in_use_);
197   in_use_ = true;
198
199   if (!need_do_bind_tex_image_)
200     return;
201
202   DCHECK(target_);
203   DoBindTexImage(target_);
204 }
205
206 void GLImageMemory::DidUseTexImage() {
207   DCHECK(in_use_);
208   in_use_ = false;
209 }
210
211 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
212                                          int z_order,
213                                          OverlayTransform transform,
214                                          const Rect& bounds_rect,
215                                          const RectF& crop_rect) {
216   return false;
217 }
218
219 void GLImageMemory::DoBindTexImage(unsigned target) {
220   TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage");
221
222   DCHECK(need_do_bind_tex_image_);
223   need_do_bind_tex_image_ = false;
224
225   DCHECK(memory_);
226 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
227     defined(USE_OZONE)
228   if (target == GL_TEXTURE_EXTERNAL_OES) {
229     if (egl_image_ == EGL_NO_IMAGE_KHR) {
230       DCHECK_EQ(0u, egl_texture_id_);
231       glGenTextures(1, &egl_texture_id_);
232
233       {
234         ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
235
236         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
237         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
238         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
239         glTexImage2D(GL_TEXTURE_2D,
240                      0,  // mip level
241                      TextureFormat(format_),
242                      size_.width(),
243                      size_.height(),
244                      0,  // border
245                      DataFormat(format_),
246                      DataType(format_),
247                      memory_);
248       }
249
250       EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
251       // Need to pass current EGL rendering context to eglCreateImageKHR for
252       // target type EGL_GL_TEXTURE_2D_KHR.
253       egl_image_ =
254           eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
255                             eglGetCurrentContext(),
256                             EGL_GL_TEXTURE_2D_KHR,
257                             reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
258                             attrs);
259       DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
260           << "Error creating EGLImage: " << eglGetError();
261     } else {
262       ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
263
264       glTexSubImage2D(GL_TEXTURE_2D,
265                       0,  // mip level
266                       0,  // x-offset
267                       0,  // y-offset
268                       size_.width(),
269                       size_.height(),
270                       DataFormat(format_),
271                       DataType(format_),
272                       memory_);
273     }
274
275     glEGLImageTargetTexture2DOES(target, egl_image_);
276     DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
277     return;
278   }
279 #endif
280
281   DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
282   glTexImage2D(target,
283                0,  // mip level
284                TextureFormat(format_),
285                size_.width(),
286                size_.height(),
287                0,  // border
288                DataFormat(format_),
289                DataType(format_),
290                memory_);
291 }
292
293 }  // namespace gfx