diff --git a/content/common/gpu/media/android_video_decode_accelerator.cc b/content/common/gpu/media/android_video_decode_accelerator.cc index be969f0873689b..41d55c86b8f4fc 100644 --- a/content/common/gpu/media/android_video_decode_accelerator.cc +++ b/content/common/gpu/media/android_video_decode_accelerator.cc @@ -122,7 +122,7 @@ bool AndroidVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, gl_decoder_->RestoreTextureUnitBindings(0); gl_decoder_->RestoreActiveTexture(); - surface_texture_ = new gfx::SurfaceTexture(surface_texture_id_); + surface_texture_ = gfx::SurfaceTexture::Create(surface_texture_id_); if (!ConfigureMediaCodec()) { LOG(ERROR) << "Failed to create MediaCodec instance."; diff --git a/content/common/gpu/media/android_video_decode_accelerator_unittest.cc b/content/common/gpu/media/android_video_decode_accelerator_unittest.cc index 1bb59897ec5910..c45069bc7fca39 100644 --- a/content/common/gpu/media/android_video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/android_video_decode_accelerator_unittest.cc @@ -72,7 +72,7 @@ class AndroidVideoDecodeAcceleratorTest : public testing::Test { bool Configure(media::VideoCodec codec) { AndroidVideoDecodeAccelerator* accelerator = static_cast(accelerator_.get()); - accelerator->surface_texture_ = new gfx::SurfaceTexture(0); + accelerator->surface_texture_ = gfx::SurfaceTexture::Create(0); accelerator->codec_ = codec; return accelerator->ConfigureMediaCodec(); } diff --git a/content/common/gpu/stream_texture_android.cc b/content/common/gpu/stream_texture_android.cc index 805534c911f200..d48891aa87d0c3 100644 --- a/content/common/gpu/stream_texture_android.cc +++ b/content/common/gpu/stream_texture_android.cc @@ -65,7 +65,7 @@ int32 StreamTexture::Create( StreamTexture::StreamTexture(GpuCommandBufferStub* owner_stub, int32 route_id, uint32 texture_id) - : surface_texture_(new gfx::SurfaceTexture(texture_id)), + : surface_texture_(gfx::SurfaceTexture::Create(texture_id)), size_(0, 0), has_valid_frame_(false), has_pending_frame_(false), diff --git a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc index 691e7ceabd86a3..534166b5eb5188 100644 --- a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc +++ b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc @@ -83,7 +83,7 @@ GLuint StreamTextureManagerInProcess::CreateStreamTexture( } scoped_refptr surface_texture( - new gfx::SurfaceTexture(texture->service_id())); + gfx::SurfaceTexture::Create(texture->service_id())); uint32 stream_id = next_id_++; base::Closure release_callback = diff --git a/gpu/command_buffer/tests/gl_unittests_android.cc b/gpu/command_buffer/tests/gl_unittests_android.cc index 671676a1fbc545..27b0cb6242ac29 100644 --- a/gpu/command_buffer/tests/gl_unittests_android.cc +++ b/gpu/command_buffer/tests/gl_unittests_android.cc @@ -39,7 +39,7 @@ TEST_F(GLSurfaceTextureTest, SimpleTest) { GLuint texture = 0xFEEDBEEF; scoped_refptr surface_texture( - new gfx::SurfaceTexture(texture)); + gfx::SurfaceTexture::Create(texture)); gfx::AcceleratedWidget window = surface_texture->CreateSurface(); EXPECT_TRUE(window != NULL); diff --git a/media/base/android/media_source_player_unittest.cc b/media/base/android/media_source_player_unittest.cc index 1b0bae71d56efb..9cb04b1829dd25 100644 --- a/media/base/android/media_source_player_unittest.cc +++ b/media/base/android/media_source_player_unittest.cc @@ -604,10 +604,10 @@ class MediaSourcePlayerTest : public testing::Test { void CreateNextTextureAndSetVideoSurface() { gfx::SurfaceTexture* surface_texture; if (surface_texture_a_is_next_) { - surface_texture_a_ = new gfx::SurfaceTexture(next_texture_id_++); + surface_texture_a_ = gfx::SurfaceTexture::Create(next_texture_id_++); surface_texture = surface_texture_a_.get(); } else { - surface_texture_b_ = new gfx::SurfaceTexture(next_texture_id_++); + surface_texture_b_ = gfx::SurfaceTexture::Create(next_texture_id_++); surface_texture = surface_texture_b_.get(); } @@ -803,7 +803,7 @@ TEST_F(MediaSourcePlayerTest, StartVideoCodecWithInvalidSurface) { // Test video decoder job will not be created when surface is invalid. scoped_refptr surface_texture( - new gfx::SurfaceTexture(0)); + gfx::SurfaceTexture::Create(0)); gfx::ScopedJavaSurface surface(surface_texture.get()); StartVideoDecoderJob(false); diff --git a/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java b/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java index 53d33036edebd7..5f4c59885f0846 100644 --- a/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java +++ b/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java @@ -25,6 +25,12 @@ private static SurfaceTexture create(int textureId) { return new SurfaceTexture(textureId); } + @CalledByNative + private static SurfaceTexture createSingleBuffered(int textureId) { + assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + return new SurfaceTexture(textureId, true); + } + @CalledByNative private static void destroy(SurfaceTexture surfaceTexture) { surfaceTexture.setOnFrameAvailableListener(null); @@ -47,6 +53,12 @@ private static void updateTexImage(SurfaceTexture surfaceTexture) { } } + @CalledByNative + private static void releaseTexImage(SurfaceTexture surfaceTexture) { + assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + surfaceTexture.releaseTexImage(); + } + @CalledByNative private static void setDefaultBufferSize(SurfaceTexture surfaceTexture, int width, int height) { diff --git a/ui/gl/android/surface_texture.cc b/ui/gl/android/surface_texture.cc index 35f9b47288b6de..a580041f3b7394 100644 --- a/ui/gl/android/surface_texture.cc +++ b/ui/gl/android/surface_texture.cc @@ -26,12 +26,25 @@ bool GlContextMethodsAvailable() { namespace gfx { -SurfaceTexture::SurfaceTexture(int texture_id) { +scoped_refptr SurfaceTexture::Create(int texture_id) { JNIEnv* env = base::android::AttachCurrentThread(); - j_surface_texture_.Reset( + return new SurfaceTexture( Java_SurfaceTexturePlatformWrapper_create(env, texture_id)); } +scoped_refptr SurfaceTexture::CreateSingleBuffered( + int texture_id) { + DCHECK(IsSingleBufferModeSupported()); + JNIEnv* env = base::android::AttachCurrentThread(); + return new SurfaceTexture( + Java_SurfaceTexturePlatformWrapper_createSingleBuffered(env, texture_id)); +} + +SurfaceTexture::SurfaceTexture( + const base::android::ScopedJavaLocalRef& j_surface_texture) { + j_surface_texture_.Reset(j_surface_texture); +} + SurfaceTexture::~SurfaceTexture() { JNIEnv* env = base::android::AttachCurrentThread(); Java_SurfaceTexturePlatformWrapper_destroy(env, j_surface_texture_.obj()); @@ -52,6 +65,13 @@ void SurfaceTexture::UpdateTexImage() { j_surface_texture_.obj()); } +void SurfaceTexture::ReleaseTexImage() { + DCHECK(IsSingleBufferModeSupported()); + JNIEnv* env = base::android::AttachCurrentThread(); + Java_SurfaceTexturePlatformWrapper_releaseTexImage(env, + j_surface_texture_.obj()); +} + void SurfaceTexture::GetTransformMatrix(float mtx[16]) { JNIEnv* env = base::android::AttachCurrentThread(); @@ -109,6 +129,10 @@ ANativeWindow* SurfaceTexture::CreateSurface() { } // static +bool SurfaceTexture::IsSingleBufferModeSupported() { + return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; +} + bool SurfaceTexture::RegisterSurfaceTexture(JNIEnv* env) { return RegisterNativesImpl(env); } diff --git a/ui/gl/android/surface_texture.h b/ui/gl/android/surface_texture.h index 62e375f796f459..05bc5a36b439e6 100644 --- a/ui/gl/android/surface_texture.h +++ b/ui/gl/android/surface_texture.h @@ -21,7 +21,9 @@ namespace gfx { class GL_EXPORT SurfaceTexture : public base::RefCountedThreadSafe{ public: - explicit SurfaceTexture(int texture_id); + static scoped_refptr Create(int texture_id); + + static scoped_refptr CreateSingleBuffered(int texture_id); // Set the listener callback, which will be invoked on the same thread that // is being called from here for registration. @@ -33,6 +35,13 @@ class GL_EXPORT SurfaceTexture // Update the texture image to the most recent frame from the image stream. void UpdateTexImage(); + // Release the texture content. This is needed only in single buffered mode + // to allow the image content producer to take ownership + // of the image buffer. + // This is *only* supported on SurfaceTexture instantiated via + // |CreateSingleBuffered(...)|. + void ReleaseTexImage(); + // Retrieve the 4x4 texture coordinate transform matrix associated with the // texture image set by the most recent call to updateTexImage. void GetTransformMatrix(float mtx[16]); @@ -57,8 +66,16 @@ class GL_EXPORT SurfaceTexture return j_surface_texture_; } + // This should only be used to guard the SurfaceTexture instantiated via + // |CreateSingleBuffered(...)| + static bool IsSingleBufferModeSupported(); + static bool RegisterSurfaceTexture(JNIEnv* env); + protected: + explicit SurfaceTexture( + const base::android::ScopedJavaLocalRef& j_surface_texture); + private: friend class base::RefCountedThreadSafe; ~SurfaceTexture();