Suppress data races in blink::Scheduler
[chromium-blink-merge.git] / ui / gl / gl_image_memory.cc
blobe92cc1f34ed6438f90f6ee64968eedf6660a8120
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.
5 #include "ui/gl/gl_image_memory.h"
7 #include "base/logging.h"
8 #include "base/trace_event/trace_event.h"
9 #include "ui/gl/gl_bindings.h"
10 #include "ui/gl/scoped_binders.h"
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
17 namespace gfx {
18 namespace {
20 bool ValidInternalFormat(unsigned internalformat) {
21 switch (internalformat) {
22 case GL_RGBA:
23 return true;
24 default:
25 return false;
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;
38 NOTREACHED();
39 return false;
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;
53 NOTREACHED();
54 return 0;
57 GLenum DataFormat(gfx::GpuMemoryBuffer::Format format) {
58 return TextureFormat(format);
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;
71 NOTREACHED();
72 return 0;
75 } // namespace
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)
88 egl_texture_id_(0u),
89 egl_image_(EGL_NO_IMAGE_KHR)
90 #endif
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
102 // static
103 bool GLImageMemory::StrideInBytes(size_t width,
104 gfx::GpuMemoryBuffer::Format format,
105 size_t* stride_in_bytes) {
106 base::CheckedNumeric<size_t> s = width;
107 switch (format) {
108 case gfx::GpuMemoryBuffer::RGBA_8888:
109 case gfx::GpuMemoryBuffer::BGRA_8888:
110 s *= 4;
111 if (!s.IsValid())
112 return false;
114 *stride_in_bytes = s.ValueOrDie();
115 return true;
116 case gfx::GpuMemoryBuffer::RGBX_8888:
117 NOTREACHED();
118 return false;
121 NOTREACHED();
122 return false;
125 bool GLImageMemory::Initialize(const unsigned char* memory,
126 gfx::GpuMemoryBuffer::Format format) {
127 if (!ValidInternalFormat(internalformat_)) {
128 LOG(ERROR) << "Invalid internalformat: " << internalformat_;
129 return false;
132 if (!ValidFormat(format)) {
133 LOG(ERROR) << "Invalid format: " << format;
134 return false;
137 DCHECK(memory);
138 DCHECK(!memory_);
139 memory_ = memory;
140 format_ = format;
141 return true;
144 void GLImageMemory::Destroy(bool have_context) {
145 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
146 defined(USE_OZONE)
147 if (egl_image_ != EGL_NO_IMAGE_KHR) {
148 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
149 egl_image_ = EGL_NO_IMAGE_KHR;
152 if (egl_texture_id_) {
153 if (have_context)
154 glDeleteTextures(1, &egl_texture_id_);
155 egl_texture_id_ = 0u;
157 #endif
158 memory_ = NULL;
161 gfx::Size GLImageMemory::GetSize() {
162 return size_;
165 bool GLImageMemory::BindTexImage(unsigned target) {
166 if (target_ && target_ != target) {
167 LOG(ERROR) << "GLImage can only be bound to one target";
168 return false;
170 target_ = target;
172 // Defer DoBindTexImage if not currently in use.
173 if (!in_use_) {
174 need_do_bind_tex_image_ = true;
175 return true;
178 DoBindTexImage(target);
179 return true;
182 bool GLImageMemory::CopyTexImage(unsigned target) {
183 TRACE_EVENT0("gpu", "GLImageMemory::CopyTexImage");
185 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexImage target.
186 if (target == GL_TEXTURE_EXTERNAL_OES)
187 return false;
189 DCHECK(memory_);
190 glTexSubImage2D(target, 0, // level
191 0, // x
192 0, // y
193 size_.width(), size_.height(), DataFormat(format_),
194 DataType(format_), memory_);
196 return true;
199 void GLImageMemory::WillUseTexImage() {
200 DCHECK(!in_use_);
201 in_use_ = true;
203 if (!need_do_bind_tex_image_)
204 return;
206 DCHECK(target_);
207 DoBindTexImage(target_);
210 void GLImageMemory::DidUseTexImage() {
211 DCHECK(in_use_);
212 in_use_ = false;
215 bool GLImageMemory::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
216 int z_order,
217 OverlayTransform transform,
218 const Rect& bounds_rect,
219 const RectF& crop_rect) {
220 return false;
223 void GLImageMemory::DoBindTexImage(unsigned target) {
224 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage");
226 DCHECK(need_do_bind_tex_image_);
227 need_do_bind_tex_image_ = false;
229 DCHECK(memory_);
230 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
231 defined(USE_OZONE)
232 if (target == GL_TEXTURE_EXTERNAL_OES) {
233 if (egl_image_ == EGL_NO_IMAGE_KHR) {
234 DCHECK_EQ(0u, egl_texture_id_);
235 glGenTextures(1, &egl_texture_id_);
238 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
243 glTexImage2D(GL_TEXTURE_2D,
244 0, // mip level
245 TextureFormat(format_),
246 size_.width(),
247 size_.height(),
248 0, // border
249 DataFormat(format_),
250 DataType(format_),
251 memory_);
254 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
255 // Need to pass current EGL rendering context to eglCreateImageKHR for
256 // target type EGL_GL_TEXTURE_2D_KHR.
257 egl_image_ =
258 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
259 eglGetCurrentContext(),
260 EGL_GL_TEXTURE_2D_KHR,
261 reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
262 attrs);
263 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
264 << "Error creating EGLImage: " << eglGetError();
265 } else {
266 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
268 glTexSubImage2D(GL_TEXTURE_2D,
269 0, // mip level
270 0, // x-offset
271 0, // y-offset
272 size_.width(),
273 size_.height(),
274 DataFormat(format_),
275 DataType(format_),
276 memory_);
279 glEGLImageTargetTexture2DOES(target, egl_image_);
280 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
281 return;
283 #endif
285 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
286 glTexImage2D(target,
287 0, // mip level
288 TextureFormat(format_),
289 size_.width(),
290 size_.height(),
291 0, // border
292 DataFormat(format_),
293 DataType(format_),
294 memory_);
297 } // namespace gfx