OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "media/gpu/android_deferred_rendering_backing_strategy.h" | 5 #include "media/gpu/android_deferred_rendering_backing_strategy.h" |
6 | 6 |
7 #include <EGL/egl.h> | 7 #include <EGL/egl.h> |
8 #include <EGL/eglext.h> | 8 #include <EGL/eglext.h> |
9 | 9 |
10 #include "base/android/build_info.h" | 10 #include "base/android/build_info.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 namespace media { | 31 namespace media { |
32 | 32 |
33 AndroidDeferredRenderingBackingStrategy:: | 33 AndroidDeferredRenderingBackingStrategy:: |
34 AndroidDeferredRenderingBackingStrategy(AVDAStateProvider* state_provider) | 34 AndroidDeferredRenderingBackingStrategy(AVDAStateProvider* state_provider) |
35 : state_provider_(state_provider), media_codec_(nullptr) {} | 35 : state_provider_(state_provider), media_codec_(nullptr) {} |
36 | 36 |
37 AndroidDeferredRenderingBackingStrategy:: | 37 AndroidDeferredRenderingBackingStrategy:: |
38 ~AndroidDeferredRenderingBackingStrategy() {} | 38 ~AndroidDeferredRenderingBackingStrategy() {} |
39 | 39 |
40 gfx::ScopedJavaSurface AndroidDeferredRenderingBackingStrategy::Initialize( | 40 gl::ScopedJavaSurface AndroidDeferredRenderingBackingStrategy::Initialize( |
41 int surface_view_id) { | 41 int surface_view_id) { |
42 shared_state_ = new AVDASharedState(); | 42 shared_state_ = new AVDASharedState(); |
43 | 43 |
44 // Create a texture for the SurfaceTexture to use. | 44 // Create a texture for the SurfaceTexture to use. |
45 GLuint service_id; | 45 GLuint service_id; |
46 glGenTextures(1, &service_id); | 46 glGenTextures(1, &service_id); |
| 47 DCHECK(service_id); |
47 shared_state_->set_surface_texture_service_id(service_id); | 48 shared_state_->set_surface_texture_service_id(service_id); |
48 | 49 |
49 glActiveTexture(GL_TEXTURE0); | 50 glActiveTexture(GL_TEXTURE0); |
50 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id); | 51 glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id); |
51 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 52 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
52 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 53 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
53 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 54 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
54 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 55 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
55 | 56 |
56 state_provider_->GetGlDecoder()->RestoreTextureUnitBindings(0); | 57 state_provider_->GetGlDecoder()->RestoreTextureUnitBindings(0); |
57 state_provider_->GetGlDecoder()->RestoreActiveTexture(); | 58 state_provider_->GetGlDecoder()->RestoreActiveTexture(); |
58 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 59 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
59 | 60 |
60 gfx::ScopedJavaSurface surface; | 61 gl::ScopedJavaSurface surface; |
61 if (surface_view_id != media::VideoDecodeAccelerator::Config::kNoSurfaceID) { | 62 if (surface_view_id != media::VideoDecodeAccelerator::Config::kNoSurfaceID) { |
62 surface = gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface( | 63 surface = gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface( |
63 surface_view_id); | 64 surface_view_id); |
64 } else { | 65 } else { |
65 bool using_virtual_context = false; | 66 bool using_virtual_context = false; |
66 if (gfx::GLContext* context = gfx::GLContext::GetCurrent()) { | 67 if (gl::GLContext* context = gl::GLContext::GetCurrent()) { |
67 if (gfx::GLShareGroup* share_group = context->share_group()) | 68 if (gl::GLShareGroup* share_group = context->share_group()) |
68 using_virtual_context = !!share_group->GetSharedContext(); | 69 using_virtual_context = !!share_group->GetSharedContext(); |
69 } | 70 } |
70 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.VirtualContext", using_virtual_context); | 71 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.VirtualContext", using_virtual_context); |
71 // Detach doesn't work so well on all platforms. Just attach the | 72 // Detach doesn't work so well on all platforms. Just attach the |
72 // SurfaceTexture here, and probably context switch later. | 73 // SurfaceTexture here, and probably context switch later. |
73 // Detaching might save us a context switch, since AVDACodecImage will | 74 // Detaching might save us a context switch, since AVDACodecImage will |
74 // attach when needed. However, given that it also fails a lot, we just | 75 // attach when needed. However, given that it also fails a lot, we just |
75 // don't do it at all. If virtual contexts are in use, then it doesn't | 76 // don't do it at all. If virtual contexts are in use, then it doesn't |
76 // even save us a context switch. | 77 // even save us a context switch. |
77 surface_texture_ = gfx::SurfaceTexture::Create(service_id); | 78 surface_texture_ = gl::SurfaceTexture::Create(service_id); |
78 shared_state_->DidAttachSurfaceTexture(); | 79 shared_state_->DidAttachSurfaceTexture(); |
79 surface = gfx::ScopedJavaSurface(surface_texture_.get()); | 80 surface = gl::ScopedJavaSurface(surface_texture_.get()); |
80 } | 81 } |
81 | 82 |
82 return surface; | 83 return surface; |
83 } | 84 } |
84 | 85 |
85 void AndroidDeferredRenderingBackingStrategy::Cleanup( | 86 void AndroidDeferredRenderingBackingStrategy::Cleanup( |
86 bool have_context, | 87 bool have_context, |
87 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { | 88 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { |
88 // If we failed before Initialize, then do nothing. | 89 // If we failed before Initialize, then do nothing. |
89 if (!shared_state_) | 90 if (!shared_state_) |
(...skipping 11 matching lines...) Expand all Loading... |
101 if (surface_texture_ && have_context && ShouldCopyPictures()) | 102 if (surface_texture_ && have_context && ShouldCopyPictures()) |
102 CopySurfaceTextureToPictures(buffers); | 103 CopySurfaceTextureToPictures(buffers); |
103 | 104 |
104 // Now that no AVDACodecImages refer to the SurfaceTexture's texture, delete | 105 // Now that no AVDACodecImages refer to the SurfaceTexture's texture, delete |
105 // the texture name. | 106 // the texture name. |
106 GLuint service_id = shared_state_->surface_texture_service_id(); | 107 GLuint service_id = shared_state_->surface_texture_service_id(); |
107 if (service_id > 0 && have_context) | 108 if (service_id > 0 && have_context) |
108 glDeleteTextures(1, &service_id); | 109 glDeleteTextures(1, &service_id); |
109 } | 110 } |
110 | 111 |
111 scoped_refptr<gfx::SurfaceTexture> | 112 scoped_refptr<gl::SurfaceTexture> |
112 AndroidDeferredRenderingBackingStrategy::GetSurfaceTexture() const { | 113 AndroidDeferredRenderingBackingStrategy::GetSurfaceTexture() const { |
113 return surface_texture_; | 114 return surface_texture_; |
114 } | 115 } |
115 | 116 |
116 uint32_t AndroidDeferredRenderingBackingStrategy::GetTextureTarget() const { | 117 uint32_t AndroidDeferredRenderingBackingStrategy::GetTextureTarget() const { |
117 // If we're using a surface texture, then we need an external texture target | 118 // If we're using a surface texture, then we need an external texture target |
118 // to sample from it. If not, then we'll use 2D transparent textures to draw | 119 // to sample from it. If not, then we'll use 2D transparent textures to draw |
119 // a transparent hole through which to see the SurfaceView. This is normally | 120 // a transparent hole through which to see the SurfaceView. This is normally |
120 // needed only for the devtools inspector, since the overlay mechanism handles | 121 // needed only for the devtools inspector, since the overlay mechanism handles |
121 // it otherwise. | 122 // it otherwise. |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 gpu::gles2::GLES2Decoder* gl_decoder = state_provider_->GetGlDecoder().get(); | 349 gpu::gles2::GLES2Decoder* gl_decoder = state_provider_->GetGlDecoder().get(); |
349 if (!gl_decoder) | 350 if (!gl_decoder) |
350 return; | 351 return; |
351 | 352 |
352 const gfx::Size size = state_provider_->GetSize(); | 353 const gfx::Size size = state_provider_->GetSize(); |
353 | 354 |
354 // Create a 2D texture to hold a copy of the SurfaceTexture's front buffer. | 355 // Create a 2D texture to hold a copy of the SurfaceTexture's front buffer. |
355 GLuint tmp_texture_id; | 356 GLuint tmp_texture_id; |
356 glGenTextures(1, &tmp_texture_id); | 357 glGenTextures(1, &tmp_texture_id); |
357 { | 358 { |
358 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id); | 359 gl::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id); |
359 // The target texture's size will exactly match the source. | 360 // The target texture's size will exactly match the source. |
360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
364 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | 365 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
365 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); | 366 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
366 } | 367 } |
367 | 368 |
368 float transform_matrix[16]; | 369 float transform_matrix[16]; |
369 surface_texture_->GetTransformMatrix(transform_matrix); | 370 surface_texture_->GetTransformMatrix(transform_matrix); |
370 | 371 |
371 gpu::CopyTextureCHROMIUMResourceManager copier; | 372 gpu::CopyTextureCHROMIUMResourceManager copier; |
372 copier.Initialize( | 373 copier.Initialize( |
373 gl_decoder, | 374 gl_decoder, |
374 gl_decoder->GetContextGroup()->feature_info()->feature_flags()); | 375 gl_decoder->GetContextGroup()->feature_info()->feature_flags()); |
375 copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES, | 376 copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES, |
376 shared_state_->surface_texture_service_id(), | 377 shared_state_->surface_texture_service_id(), |
377 GL_TEXTURE_2D, tmp_texture_id, size.width(), | 378 GL_TEXTURE_2D, tmp_texture_id, size.width(), |
378 size.height(), true, false, false, | 379 size.height(), true, false, false, |
379 transform_matrix); | 380 transform_matrix); |
380 | 381 |
381 // Create an EGLImage from the 2D texture we just copied into. By associating | 382 // Create an EGLImage from the 2D texture we just copied into. By associating |
382 // the EGLImage with the PictureBuffer textures they will remain valid even | 383 // the EGLImage with the PictureBuffer textures they will remain valid even |
383 // after we delete the 2D texture and EGLImage. | 384 // after we delete the 2D texture and EGLImage. |
384 const EGLImageKHR egl_image = eglCreateImageKHR( | 385 const EGLImageKHR egl_image = eglCreateImageKHR( |
385 gfx::GLSurfaceEGL::GetHardwareDisplay(), eglGetCurrentContext(), | 386 gl::GLSurfaceEGL::GetHardwareDisplay(), eglGetCurrentContext(), |
386 EGL_GL_TEXTURE_2D_KHR, reinterpret_cast<EGLClientBuffer>(tmp_texture_id), | 387 EGL_GL_TEXTURE_2D_KHR, reinterpret_cast<EGLClientBuffer>(tmp_texture_id), |
387 nullptr /* attrs */); | 388 nullptr /* attrs */); |
388 | 389 |
389 glDeleteTextures(1, &tmp_texture_id); | 390 glDeleteTextures(1, &tmp_texture_id); |
390 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 391 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
391 | 392 |
392 if (egl_image == EGL_NO_IMAGE_KHR) { | 393 if (egl_image == EGL_NO_IMAGE_KHR) { |
393 DLOG(ERROR) << "Failed creating EGLImage: " << ui::GetLastEGLErrorString(); | 394 DLOG(ERROR) << "Failed creating EGLImage: " << ui::GetLastEGLErrorString(); |
394 return; | 395 return; |
395 } | 396 } |
396 | 397 |
397 for (const std::pair<int, media::PictureBuffer>& entry : buffers) { | 398 for (const std::pair<int, media::PictureBuffer>& entry : buffers) { |
398 gpu::gles2::TextureRef* texture_ref = | 399 gpu::gles2::TextureRef* texture_ref = |
399 state_provider_->GetTextureForPicture(entry.second); | 400 state_provider_->GetTextureForPicture(entry.second); |
400 if (!texture_ref) | 401 if (!texture_ref) |
401 continue; | 402 continue; |
402 gfx::ScopedTextureBinder texture_binder( | 403 gl::ScopedTextureBinder texture_binder( |
403 GL_TEXTURE_EXTERNAL_OES, texture_ref->texture()->service_id()); | 404 GL_TEXTURE_EXTERNAL_OES, texture_ref->texture()->service_id()); |
404 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); | 405 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); |
405 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 406 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
406 } | 407 } |
407 | 408 |
408 EGLBoolean result = | 409 EGLBoolean result = |
409 eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), egl_image); | 410 eglDestroyImageKHR(gl::GLSurfaceEGL::GetHardwareDisplay(), egl_image); |
410 if (result == EGL_FALSE) { | 411 if (result == EGL_FALSE) { |
411 DLOG(ERROR) << "Error destroying EGLImage: " << ui::GetLastEGLErrorString(); | 412 DLOG(ERROR) << "Error destroying EGLImage: " << ui::GetLastEGLErrorString(); |
412 } | 413 } |
413 } | 414 } |
414 | 415 |
415 bool AndroidDeferredRenderingBackingStrategy::ShouldCopyPictures() const { | 416 bool AndroidDeferredRenderingBackingStrategy::ShouldCopyPictures() const { |
416 // See if there's a workaround. | 417 // See if there's a workaround. |
417 if (gpu::gles2::GLES2Decoder* gl_decoder = | 418 if (gpu::gles2::GLES2Decoder* gl_decoder = |
418 state_provider_->GetGlDecoder().get()) { | 419 state_provider_->GetGlDecoder().get()) { |
419 if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) { | 420 if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) { |
(...skipping 23 matching lines...) Expand all Loading... |
443 model.find("sm-t285") != std::string::npos || | 444 model.find("sm-t285") != std::string::npos || |
444 model.find("sm-j320") != std::string::npos) | 445 model.find("sm-j320") != std::string::npos) |
445 return false; | 446 return false; |
446 } | 447 } |
447 } | 448 } |
448 | 449 |
449 return true; | 450 return true; |
450 } | 451 } |
451 | 452 |
452 } // namespace media | 453 } // namespace media |
OLD | NEW |