OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gl/gl_image_memory.h" | 5 #include "ui/gl/gl_image_memory.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/trace_event/trace_event.h" | 8 #include "base/trace_event/trace_event.h" |
9 #include "ui/gl/gl_bindings.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 | 10 |
17 namespace gfx { | 11 namespace gfx { |
18 namespace { | 12 namespace { |
19 | 13 |
20 bool ValidInternalFormat(unsigned internalformat) { | 14 bool ValidInternalFormat(unsigned internalformat) { |
21 switch (internalformat) { | 15 switch (internalformat) { |
22 case GL_ATC_RGB_AMD: | 16 case GL_ATC_RGB_AMD: |
23 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: | 17 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: |
24 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | 18 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: |
25 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | 19 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 size.width(), format, &stride_in_bytes); | 139 size.width(), format, &stride_in_bytes); |
146 DCHECK(valid_stride); | 140 DCHECK(valid_stride); |
147 return static_cast<GLsizei>(stride_in_bytes * size.height()); | 141 return static_cast<GLsizei>(stride_in_bytes * size.height()); |
148 } | 142 } |
149 | 143 |
150 } // namespace | 144 } // namespace |
151 | 145 |
152 GLImageMemory::GLImageMemory(const Size& size, unsigned internalformat) | 146 GLImageMemory::GLImageMemory(const Size& size, unsigned internalformat) |
153 : size_(size), | 147 : size_(size), |
154 internalformat_(internalformat), | 148 internalformat_(internalformat), |
155 memory_(NULL), | 149 memory_(nullptr), |
156 format_(BufferFormat::RGBA_8888), | 150 format_(BufferFormat::RGBA_8888) {} |
157 in_use_(false), | |
158 target_(0), | |
159 need_do_bind_tex_image_(false) | |
160 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | |
161 defined(USE_OZONE) | |
162 , | |
163 egl_texture_id_(0u), | |
164 egl_image_(EGL_NO_IMAGE_KHR) | |
165 #endif | |
166 { | |
167 } | |
168 | 151 |
169 GLImageMemory::~GLImageMemory() { | 152 GLImageMemory::~GLImageMemory() { |
170 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | 153 DCHECK(!memory_); |
171 defined(USE_OZONE) | |
172 DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); | |
173 DCHECK_EQ(0u, egl_texture_id_); | |
174 #endif | |
175 } | 154 } |
176 | 155 |
177 // static | 156 // static |
178 bool GLImageMemory::StrideInBytes(size_t width, | 157 bool GLImageMemory::StrideInBytes(size_t width, |
179 BufferFormat format, | 158 BufferFormat format, |
180 size_t* stride_in_bytes) { | 159 size_t* stride_in_bytes) { |
181 base::CheckedNumeric<size_t> checked_stride = width; | 160 base::CheckedNumeric<size_t> checked_stride = width; |
182 switch (format) { | 161 switch (format) { |
183 case BufferFormat::ATCIA: | 162 case BufferFormat::ATCIA: |
184 case BufferFormat::DXT5: | 163 case BufferFormat::DXT5: |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 DCHECK(memory); | 215 DCHECK(memory); |
237 DCHECK(!memory_); | 216 DCHECK(!memory_); |
238 DCHECK_IMPLIES(IsCompressedFormat(format), size_.width() % 4 == 0); | 217 DCHECK_IMPLIES(IsCompressedFormat(format), size_.width() % 4 == 0); |
239 DCHECK_IMPLIES(IsCompressedFormat(format), size_.height() % 4 == 0); | 218 DCHECK_IMPLIES(IsCompressedFormat(format), size_.height() % 4 == 0); |
240 memory_ = memory; | 219 memory_ = memory; |
241 format_ = format; | 220 format_ = format; |
242 return true; | 221 return true; |
243 } | 222 } |
244 | 223 |
245 void GLImageMemory::Destroy(bool have_context) { | 224 void GLImageMemory::Destroy(bool have_context) { |
246 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | 225 memory_ = nullptr; |
247 defined(USE_OZONE) | |
248 if (egl_image_ != EGL_NO_IMAGE_KHR) { | |
249 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); | |
250 egl_image_ = EGL_NO_IMAGE_KHR; | |
251 } | |
252 | |
253 if (egl_texture_id_) { | |
254 if (have_context) | |
255 glDeleteTextures(1, &egl_texture_id_); | |
256 egl_texture_id_ = 0u; | |
257 } | |
258 #endif | |
259 memory_ = NULL; | |
260 } | 226 } |
261 | 227 |
262 Size GLImageMemory::GetSize() { | 228 Size GLImageMemory::GetSize() { |
263 return size_; | 229 return size_; |
264 } | 230 } |
265 | 231 |
266 unsigned GLImageMemory::GetInternalFormat() { | 232 unsigned GLImageMemory::GetInternalFormat() { |
267 return internalformat_; | 233 return internalformat_; |
268 } | 234 } |
269 | 235 |
270 bool GLImageMemory::BindTexImage(unsigned target) { | 236 bool GLImageMemory::BindTexImage(unsigned target) { |
271 if (target_ && target_ != target) { | 237 return false; |
272 LOG(ERROR) << "GLImage can only be bound to one target"; | 238 } |
| 239 |
| 240 bool GLImageMemory::CopyTexImage(unsigned target) { |
| 241 TRACE_EVENT2("gpu", "GLImageMemory::CopyTexImage", "width", size_.width(), |
| 242 "height", size_.height()); |
| 243 |
| 244 // GL_TEXTURE_EXTERNAL_OES is not a supported target. |
| 245 if (target == GL_TEXTURE_EXTERNAL_OES) |
273 return false; | 246 return false; |
274 } | |
275 target_ = target; | |
276 | 247 |
277 // Defer DoBindTexImage if not currently in use. | 248 if (IsCompressedFormat(format_)) { |
278 if (!in_use_) { | 249 glCompressedTexImage2D(target, 0, TextureFormat(format_), size_.width(), |
279 need_do_bind_tex_image_ = true; | 250 size_.height(), 0, SizeInBytes(size_, format_), |
280 return true; | 251 memory_); |
| 252 } else { |
| 253 glTexImage2D(target, 0, TextureFormat(format_), size_.width(), |
| 254 size_.height(), 0, DataFormat(format_), DataType(format_), |
| 255 memory_); |
281 } | 256 } |
282 | 257 |
283 DoBindTexImage(target); | |
284 return true; | 258 return true; |
285 } | 259 } |
286 | 260 |
287 bool GLImageMemory::CopyTexSubImage(unsigned target, | 261 bool GLImageMemory::CopyTexSubImage(unsigned target, |
288 const Point& offset, | 262 const Point& offset, |
289 const Rect& rect) { | 263 const Rect& rect) { |
290 TRACE_EVENT2("gpu", "GLImageMemory::CopyTexSubImage", "width", rect.width(), | 264 TRACE_EVENT2("gpu", "GLImageMemory::CopyTexSubImage", "width", rect.width(), |
291 "height", rect.height()); | 265 "height", rect.height()); |
292 | 266 |
293 // GL_TEXTURE_EXTERNAL_OES is not a supported CopyTexSubImage target. | 267 // GL_TEXTURE_EXTERNAL_OES is not a supported target. |
294 if (target == GL_TEXTURE_EXTERNAL_OES) | 268 if (target == GL_TEXTURE_EXTERNAL_OES) |
295 return false; | 269 return false; |
296 | 270 |
297 // Sub width is not supported. | 271 // Sub width is not supported. |
298 if (rect.width() != size_.width()) | 272 if (rect.width() != size_.width()) |
299 return false; | 273 return false; |
300 | 274 |
301 // Height must be a multiple of 4 if compressed. | 275 // Height must be a multiple of 4 if compressed. |
302 if (IsCompressedFormat(format_) && rect.height() % 4) | 276 if (IsCompressedFormat(format_) && rect.height() % 4) |
303 return false; | 277 return false; |
304 | 278 |
305 size_t stride_in_bytes = 0; | 279 size_t stride_in_bytes = 0; |
306 bool rv = StrideInBytes(size_.width(), format_, &stride_in_bytes); | 280 bool rv = StrideInBytes(size_.width(), format_, &stride_in_bytes); |
307 DCHECK(rv); | 281 DCHECK(rv); |
308 DCHECK(memory_); | 282 DCHECK(memory_); |
309 const unsigned char* data = memory_ + rect.y() * stride_in_bytes; | 283 const unsigned char* data = memory_ + rect.y() * stride_in_bytes; |
310 if (IsCompressedFormat(format_)) { | 284 if (IsCompressedFormat(format_)) { |
311 glCompressedTexSubImage2D(target, | 285 glCompressedTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(), |
312 0, // level | |
313 offset.x(), offset.y(), rect.width(), | |
314 rect.height(), DataFormat(format_), | 286 rect.height(), DataFormat(format_), |
315 SizeInBytes(rect.size(), format_), data); | 287 SizeInBytes(rect.size(), format_), data); |
316 } else { | 288 } else { |
317 glTexSubImage2D(target, 0, // level | 289 glTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(), |
318 offset.x(), offset.y(), rect.width(), rect.height(), | 290 rect.height(), DataFormat(format_), DataType(format_), |
319 DataFormat(format_), DataType(format_), data); | 291 data); |
320 } | 292 } |
321 | 293 |
322 return true; | 294 return true; |
323 } | 295 } |
324 | 296 |
325 void GLImageMemory::WillUseTexImage() { | |
326 DCHECK(!in_use_); | |
327 in_use_ = true; | |
328 | |
329 if (!need_do_bind_tex_image_) | |
330 return; | |
331 | |
332 DCHECK(target_); | |
333 DoBindTexImage(target_); | |
334 } | |
335 | |
336 void GLImageMemory::DidUseTexImage() { | |
337 DCHECK(in_use_); | |
338 in_use_ = false; | |
339 } | |
340 | |
341 bool GLImageMemory::ScheduleOverlayPlane(AcceleratedWidget widget, | 297 bool GLImageMemory::ScheduleOverlayPlane(AcceleratedWidget widget, |
342 int z_order, | 298 int z_order, |
343 OverlayTransform transform, | 299 OverlayTransform transform, |
344 const Rect& bounds_rect, | 300 const Rect& bounds_rect, |
345 const RectF& crop_rect) { | 301 const RectF& crop_rect) { |
346 return false; | 302 return false; |
347 } | 303 } |
348 | 304 |
349 void GLImageMemory::DoBindTexImage(unsigned target) { | |
350 TRACE_EVENT0("gpu", "GLImageMemory::DoBindTexImage"); | |
351 | |
352 DCHECK(need_do_bind_tex_image_); | |
353 need_do_bind_tex_image_ = false; | |
354 | |
355 DCHECK(memory_); | |
356 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | |
357 defined(USE_OZONE) | |
358 if (target == GL_TEXTURE_EXTERNAL_OES) { | |
359 if (egl_image_ == EGL_NO_IMAGE_KHR) { | |
360 DCHECK_EQ(0u, egl_texture_id_); | |
361 glGenTextures(1, &egl_texture_id_); | |
362 | |
363 { | |
364 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | |
365 | |
366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
369 if (IsCompressedFormat(format_)) { | |
370 glCompressedTexImage2D(GL_TEXTURE_2D, | |
371 0, // mip level | |
372 TextureFormat(format_), size_.width(), | |
373 size_.height(), | |
374 0, // border | |
375 SizeInBytes(size_, format_), memory_); | |
376 } else { | |
377 glTexImage2D(GL_TEXTURE_2D, | |
378 0, // mip level | |
379 TextureFormat(format_), | |
380 size_.width(), | |
381 size_.height(), | |
382 0, // border | |
383 DataFormat(format_), | |
384 DataType(format_), | |
385 memory_); | |
386 } | |
387 } | |
388 | |
389 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | |
390 // Need to pass current EGL rendering context to eglCreateImageKHR for | |
391 // target type EGL_GL_TEXTURE_2D_KHR. | |
392 egl_image_ = | |
393 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), | |
394 eglGetCurrentContext(), | |
395 EGL_GL_TEXTURE_2D_KHR, | |
396 reinterpret_cast<EGLClientBuffer>(egl_texture_id_), | |
397 attrs); | |
398 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) | |
399 << "Error creating EGLImage: " << eglGetError(); | |
400 } else { | |
401 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | |
402 | |
403 if (IsCompressedFormat(format_)) { | |
404 glCompressedTexSubImage2D(GL_TEXTURE_2D, | |
405 0, // mip level | |
406 0, // x-offset | |
407 0, // y-offset | |
408 size_.width(), size_.height(), | |
409 DataFormat(format_), | |
410 SizeInBytes(size_, format_), memory_); | |
411 } else { | |
412 glTexSubImage2D(GL_TEXTURE_2D, | |
413 0, // mip level | |
414 0, // x-offset | |
415 0, // y-offset | |
416 size_.width(), | |
417 size_.height(), | |
418 DataFormat(format_), | |
419 DataType(format_), | |
420 memory_); | |
421 } | |
422 } | |
423 | |
424 glEGLImageTargetTexture2DOES(target, egl_image_); | |
425 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
426 return; | |
427 } | |
428 #endif | |
429 | |
430 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); | |
431 if (IsCompressedFormat(format_)) { | |
432 glCompressedTexImage2D(target, | |
433 0, // mip level | |
434 TextureFormat(format_), size_.width(), | |
435 size_.height(), | |
436 0, // border | |
437 SizeInBytes(size_, format_), memory_); | |
438 } else { | |
439 glTexImage2D(target, | |
440 0, // mip level | |
441 TextureFormat(format_), | |
442 size_.width(), | |
443 size_.height(), | |
444 0, // border | |
445 DataFormat(format_), | |
446 DataType(format_), | |
447 memory_); | |
448 } | |
449 } | |
450 | |
451 void GLImageMemory::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, | |
452 uint64_t process_tracing_id, | |
453 const std::string& dump_name) { | |
454 // Note that the following calculation does not consider whether this GLImage | |
455 // has been un-bound from a texture. It also relies on this GLImage only ever | |
456 // being bound to a single texture. We could check these conditions more | |
457 // thoroughly, but at the cost of extra GL queries. | |
458 bool is_bound_to_texture = target_ && !need_do_bind_tex_image_; | |
459 | |
460 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | |
461 defined(USE_OZONE) | |
462 is_bound_to_texture |= !!egl_texture_id_; | |
463 #endif | |
464 | |
465 size_t size_in_bytes = is_bound_to_texture ? SizeInBytes(size_, format_) : 0; | |
466 | |
467 base::trace_event::MemoryAllocatorDump* dump = | |
468 pmd->CreateAllocatorDump(dump_name + "/texture_memory"); | |
469 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | |
470 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | |
471 static_cast<uint64_t>(size_in_bytes)); | |
472 | |
473 // No need for a global shared edge here. This object in the GPU process is | |
474 // the sole owner of this texture id. | |
475 } | |
476 | |
477 } // namespace gfx | 305 } // namespace gfx |
OLD | NEW |