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 "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" | 5 #include "content/common/gpu/media/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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 const { | 112 const { |
113 // For SurfaceView, request a 1x1 2D texture to reduce memory during | 113 // For SurfaceView, request a 1x1 2D texture to reduce memory during |
114 // initialization. For SurfaceTexture, allocate a picture buffer that is the | 114 // initialization. For SurfaceTexture, allocate a picture buffer that is the |
115 // actual frame size. Note that it will be an external texture anyway, so it | 115 // actual frame size. Note that it will be an external texture anyway, so it |
116 // doesn't allocate an image of that size. However, it's still important to | 116 // doesn't allocate an image of that size. However, it's still important to |
117 // get the coded size right, so that VideoLayerImpl doesn't try to scale the | 117 // get the coded size right, so that VideoLayerImpl doesn't try to scale the |
118 // texture when building the quad for it. | 118 // texture when building the quad for it. |
119 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); | 119 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); |
120 } | 120 } |
121 | 121 |
122 AVDACodecImage* AndroidDeferredRenderingBackingStrategy::GetImageForPicture( | |
123 const media::PictureBuffer& picture_buffer) { | |
124 gpu::gles2::TextureRef* texture_ref = | |
125 state_provider_->GetTextureForPicture(picture_buffer); | |
126 RETURN_NULL_IF_NULL(texture_ref); | |
127 gl::GLImage* image = | |
128 texture_ref->texture()->GetLevelImage(GetTextureTarget(), 0); | |
129 return static_cast<AVDACodecImage*>(image); | |
130 } | |
131 | |
132 void AndroidDeferredRenderingBackingStrategy::SetImageForPicture( | 122 void AndroidDeferredRenderingBackingStrategy::SetImageForPicture( |
133 const media::PictureBuffer& picture_buffer, | 123 const media::PictureBuffer& picture_buffer, |
134 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { | 124 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { |
135 gpu::gles2::TextureRef* texture_ref = | 125 gpu::gles2::TextureRef* texture_ref = |
136 state_provider_->GetTextureForPicture(picture_buffer); | 126 state_provider_->GetTextureForPicture(picture_buffer); |
137 RETURN_IF_NULL(texture_ref); | 127 RETURN_IF_NULL(texture_ref); |
138 | 128 |
139 gpu::gles2::TextureManager* texture_manager = | 129 gpu::gles2::TextureManager* texture_manager = |
140 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); | 130 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); |
141 RETURN_IF_NULL(texture_manager); | 131 RETURN_IF_NULL(texture_manager); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 } | 167 } |
178 | 168 |
179 void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer( | 169 void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer( |
180 int32_t codec_buf_index, | 170 int32_t codec_buf_index, |
181 const media::PictureBuffer& picture_buffer) { | 171 const media::PictureBuffer& picture_buffer) { |
182 // Make sure that the decoder is available. | 172 // Make sure that the decoder is available. |
183 RETURN_IF_NULL(state_provider_->GetGlDecoder()); | 173 RETURN_IF_NULL(state_provider_->GetGlDecoder()); |
184 | 174 |
185 // Notify the AVDACodecImage for picture_buffer that it should use the | 175 // Notify the AVDACodecImage for picture_buffer that it should use the |
186 // decoded buffer codec_buf_index to render this frame. | 176 // decoded buffer codec_buf_index to render this frame. |
187 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer); | 177 AVDACodecImage* avda_image = |
| 178 shared_state_->GetImageForPicture(picture_buffer.id()); |
188 RETURN_IF_NULL(avda_image); | 179 RETURN_IF_NULL(avda_image); |
189 DCHECK_EQ(avda_image->GetMediaCodecBufferIndex(), -1); | 180 DCHECK_EQ(avda_image->GetMediaCodecBufferIndex(), -1); |
190 // Note that this is not a race, since we do not re-use a PictureBuffer | 181 // Note that this is not a race, since we do not re-use a PictureBuffer |
191 // until after the CC is done drawing it. | 182 // until after the CC is done drawing it. |
192 avda_image->SetMediaCodecBufferIndex(codec_buf_index); | 183 avda_image->SetMediaCodecBufferIndex(codec_buf_index); |
193 avda_image->SetSize(state_provider_->GetSize()); | 184 avda_image->SetSize(state_provider_->GetSize()); |
194 } | 185 } |
195 | 186 |
196 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( | 187 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( |
197 const media::PictureBuffer& picture_buffer, | 188 const media::PictureBuffer& picture_buffer, |
198 bool have_context) { | 189 bool have_context) { |
199 // Attach a GLImage to each texture that will use the surface texture. | 190 // Attach a GLImage to each texture that will use the surface texture. |
200 // We use a refptr here in case SetImageForPicture fails. | 191 // We use a refptr here in case SetImageForPicture fails. |
201 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = | 192 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = |
202 new AVDACodecImage(shared_state_, media_codec_, | 193 new AVDACodecImage(picture_buffer.id(), shared_state_, media_codec_, |
203 state_provider_->GetGlDecoder(), surface_texture_); | 194 state_provider_->GetGlDecoder(), surface_texture_); |
204 SetImageForPicture(picture_buffer, gl_image); | 195 SetImageForPicture(picture_buffer, gl_image); |
205 | 196 |
206 if (!surface_texture_ && have_context) { | 197 if (!surface_texture_ && have_context) { |
207 // To make devtools work, we're using a 2D texture. Make it transparent, | 198 // To make devtools work, we're using a 2D texture. Make it transparent, |
208 // so that it draws a hole for the SV to show through. This is only | 199 // so that it draws a hole for the SV to show through. This is only |
209 // because devtools draws and reads back, which skips overlay processing. | 200 // because devtools draws and reads back, which skips overlay processing. |
210 // It's unclear why devtools renders twice -- once normally, and once | 201 // It's unclear why devtools renders twice -- once normally, and once |
211 // including a readback layer. The result is that the device screen | 202 // including a readback layer. The result is that the device screen |
212 // flashes as we alternately draw the overlay hole and this texture, | 203 // flashes as we alternately draw the overlay hole and this texture, |
213 // unless we make the texture transparent. | 204 // unless we make the texture transparent. |
214 static const uint8_t rgba[] = {0, 0, 0, 0}; | 205 static const uint8_t rgba[] = {0, 0, 0, 0}; |
215 const gfx::Size size(1, 1); | 206 const gfx::Size size(1, 1); |
216 DCHECK_LE(1u, picture_buffer.texture_ids().size()); | 207 DCHECK_LE(1u, picture_buffer.texture_ids().size()); |
217 glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]); | 208 glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]); |
218 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | 209 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
219 GL_RGBA, GL_UNSIGNED_BYTE, rgba); | 210 GL_RGBA, GL_UNSIGNED_BYTE, rgba); |
220 } | 211 } |
221 } | 212 } |
222 | 213 |
223 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture( | 214 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture( |
224 const media::PictureBuffer& picture_buffer) { | 215 const media::PictureBuffer& picture_buffer) { |
225 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer); | 216 AVDACodecImage* avda_image = |
| 217 shared_state_->GetImageForPicture(picture_buffer.id()); |
| 218 RETURN_IF_NULL(avda_image); |
226 | 219 |
227 // See if there is a media codec buffer still attached to this image. | 220 // See if there is a media codec buffer still attached to this image. |
228 const int32_t codec_buffer = avda_image->GetMediaCodecBufferIndex(); | 221 const int32_t codec_buffer = avda_image->GetMediaCodecBufferIndex(); |
229 | 222 |
230 if (codec_buffer >= 0) { | 223 if (codec_buffer >= 0) { |
231 // PictureBuffer wasn't displayed, so release the buffer. | 224 // PictureBuffer wasn't displayed, so release the buffer. |
232 media_codec_->ReleaseOutputBuffer(codec_buffer, false); | 225 media_codec_->ReleaseOutputBuffer(codec_buffer, false); |
233 avda_image->SetMediaCodecBufferIndex(-1); | 226 avda_image->SetMediaCodecBufferIndex(-1); |
234 } | 227 } |
235 } | 228 } |
236 | 229 |
237 void AndroidDeferredRenderingBackingStrategy::ReuseOnePictureBuffer( | 230 void AndroidDeferredRenderingBackingStrategy::ReuseOnePictureBuffer( |
238 const media::PictureBuffer& picture_buffer) { | 231 const media::PictureBuffer& picture_buffer) { |
239 // At this point, the CC must be done with the picture. We can't really | 232 // At this point, the CC must be done with the picture. We can't really |
240 // check for that here directly. it's guaranteed in gpu_video_decoder.cc, | 233 // check for that here directly. it's guaranteed in gpu_video_decoder.cc, |
241 // when it waits on the sync point before releasing the mailbox. That sync | 234 // when it waits on the sync point before releasing the mailbox. That sync |
242 // point is inserted by destroying the resource in VideoLayerImpl::DidDraw. | 235 // point is inserted by destroying the resource in VideoLayerImpl::DidDraw. |
243 ReleaseCodecBufferForPicture(picture_buffer); | 236 ReleaseCodecBufferForPicture(picture_buffer); |
244 } | 237 } |
245 | 238 |
246 void AndroidDeferredRenderingBackingStrategy::CodecChanged( | 239 void AndroidDeferredRenderingBackingStrategy::CodecChanged( |
247 media::VideoCodecBridge* codec, | 240 media::VideoCodecBridge* codec) { |
248 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { | |
249 // Clear any outstanding codec buffer indices, since the new codec (if any) | |
250 // doesn't know about them. | |
251 media_codec_ = codec; | 241 media_codec_ = codec; |
252 for (const std::pair<int, media::PictureBuffer>& entry : buffers) { | 242 shared_state_->CodecChanged(codec); |
253 AVDACodecImage* avda_image = GetImageForPicture(entry.second); | |
254 avda_image->SetMediaCodec(codec); | |
255 avda_image->SetMediaCodecBufferIndex(-1); | |
256 } | |
257 } | 243 } |
258 | 244 |
259 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { | 245 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { |
260 shared_state_->SignalFrameAvailable(); | 246 shared_state_->SignalFrameAvailable(); |
261 } | 247 } |
262 | 248 |
263 bool AndroidDeferredRenderingBackingStrategy::ArePicturesOverlayable() { | 249 bool AndroidDeferredRenderingBackingStrategy::ArePicturesOverlayable() { |
264 // SurfaceView frames are always overlayable because that's the only way to | 250 // SurfaceView frames are always overlayable because that's the only way to |
265 // display them. | 251 // display them. |
266 return !surface_texture_; | 252 return !surface_texture_; |
(...skipping 29 matching lines...) Expand all Loading... |
296 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id); | 282 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id); |
297 // The target texture's size will exactly match the source. | 283 // The target texture's size will exactly match the source. |
298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 285 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | 288 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
303 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); | 289 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
304 } | 290 } |
305 | 291 |
306 | |
307 | |
308 float transform_matrix[16]; | 292 float transform_matrix[16]; |
309 surface_texture_->GetTransformMatrix(transform_matrix); | 293 surface_texture_->GetTransformMatrix(transform_matrix); |
310 | 294 |
311 gpu::CopyTextureCHROMIUMResourceManager copier; | 295 gpu::CopyTextureCHROMIUMResourceManager copier; |
312 copier.Initialize( | 296 copier.Initialize( |
313 gl_decoder, | 297 gl_decoder, |
314 gl_decoder->GetContextGroup()->feature_info()->feature_flags()); | 298 gl_decoder->GetContextGroup()->feature_info()->feature_flags()); |
315 copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES, | 299 copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES, |
316 shared_state_->surface_texture_service_id(), | 300 shared_state_->surface_texture_service_id(), |
317 GL_TEXTURE_2D, tmp_texture_id, size.width(), | 301 GL_TEXTURE_2D, tmp_texture_id, size.width(), |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 return !feature_info->workarounds().avda_dont_copy_pictures; | 381 return !feature_info->workarounds().avda_dont_copy_pictures; |
398 } | 382 } |
399 } | 383 } |
400 } | 384 } |
401 | 385 |
402 // Assume so. | 386 // Assume so. |
403 return true; | 387 return true; |
404 } | 388 } |
405 | 389 |
406 } // namespace content | 390 } // namespace content |
OLD | NEW |