| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 | 72 |
| 73 void AndroidDeferredRenderingBackingStrategy::Cleanup( | 73 void AndroidDeferredRenderingBackingStrategy::Cleanup( |
| 74 bool have_context, | 74 bool have_context, |
| 75 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { | 75 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { |
| 76 // If we failed before Initialize, then do nothing. | 76 // If we failed before Initialize, then do nothing. |
| 77 if (!shared_state_) | 77 if (!shared_state_) |
| 78 return; | 78 return; |
| 79 | 79 |
| 80 // Make sure that no PictureBuffer textures refer to the SurfaceTexture or to | 80 // Make sure that no PictureBuffer textures refer to the SurfaceTexture or to |
| 81 // the service_id that we created for it. | 81 // the service_id that we created for it. |
| 82 for (const std::pair<int, media::PictureBuffer>& entry : buffers) | 82 for (const std::pair<int, media::PictureBuffer>& entry : buffers) { |
| 83 ReleaseCodecBufferForPicture(entry.second); |
| 83 SetImageForPicture(entry.second, nullptr); | 84 SetImageForPicture(entry.second, nullptr); |
| 85 } |
| 84 | 86 |
| 85 // If we're rendering to a SurfaceTexture we can make a copy of the current | 87 // If we're rendering to a SurfaceTexture we can make a copy of the current |
| 86 // front buffer so that the PictureBuffer textures are still valid. | 88 // front buffer so that the PictureBuffer textures are still valid. |
| 87 if (surface_texture_ && have_context && ShouldCopyPictures()) | 89 if (surface_texture_ && have_context && ShouldCopyPictures()) |
| 88 CopySurfaceTextureToPictures(buffers); | 90 CopySurfaceTextureToPictures(buffers); |
| 89 | 91 |
| 90 // Now that no AVDACodecImages refer to the SurfaceTexture's texture, delete | 92 // Now that no AVDACodecImages refer to the SurfaceTexture's texture, delete |
| 91 // the texture name. | 93 // the texture name. |
| 92 GLuint service_id = shared_state_->surface_texture_service_id(); | 94 GLuint service_id = shared_state_->surface_texture_service_id(); |
| 93 if (service_id > 0 && have_context) | 95 if (service_id > 0 && have_context) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 112 const { | 114 const { |
| 113 // For SurfaceView, request a 1x1 2D texture to reduce memory during | 115 // For SurfaceView, request a 1x1 2D texture to reduce memory during |
| 114 // initialization. For SurfaceTexture, allocate a picture buffer that is the | 116 // 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 | 117 // 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 | 118 // 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 | 119 // get the coded size right, so that VideoLayerImpl doesn't try to scale the |
| 118 // texture when building the quad for it. | 120 // texture when building the quad for it. |
| 119 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); | 121 return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); |
| 120 } | 122 } |
| 121 | 123 |
| 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( | 124 void AndroidDeferredRenderingBackingStrategy::SetImageForPicture( |
| 133 const media::PictureBuffer& picture_buffer, | 125 const media::PictureBuffer& picture_buffer, |
| 134 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { | 126 const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) { |
| 135 gpu::gles2::TextureRef* texture_ref = | 127 gpu::gles2::TextureRef* texture_ref = |
| 136 state_provider_->GetTextureForPicture(picture_buffer); | 128 state_provider_->GetTextureForPicture(picture_buffer); |
| 137 RETURN_IF_NULL(texture_ref); | 129 RETURN_IF_NULL(texture_ref); |
| 138 | 130 |
| 139 gpu::gles2::TextureManager* texture_manager = | 131 gpu::gles2::TextureManager* texture_manager = |
| 140 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); | 132 state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager(); |
| 141 RETURN_IF_NULL(texture_manager); | 133 RETURN_IF_NULL(texture_manager); |
| 142 | 134 |
| 143 if (image) { | 135 if (image) { |
| 144 // Also set the parameters for the level if we're not clearing | 136 // Also set the parameters for the level if we're not clearing |
| 145 // the image. | 137 // the image. |
| 146 const gfx::Size size = state_provider_->GetSize(); | 138 const gfx::Size size = state_provider_->GetSize(); |
| 147 texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA, | 139 texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA, |
| 148 size.width(), size.height(), 1, 0, GL_RGBA, | 140 size.width(), size.height(), 1, 0, GL_RGBA, |
| 149 GL_UNSIGNED_BYTE, gfx::Rect()); | 141 GL_UNSIGNED_BYTE, gfx::Rect()); |
| 150 | 142 |
| 151 // Override the texture's service_id, so that it will use the one that | 143 // Override the texture's service_id, so that it will use the one that |
| 152 // will be / is attached to the SurfaceTexture. | 144 // will be / is attached to the SurfaceTexture. |
| 153 DCHECK(shared_state_->surface_texture_service_id()); | 145 DCHECK(shared_state_->surface_texture_service_id()); |
| 154 texture_ref->texture()->SetUnownedServiceId( | 146 texture_ref->texture()->SetUnownedServiceId( |
| 155 shared_state_->surface_texture_service_id()); | 147 shared_state_->surface_texture_service_id()); |
| 156 | 148 |
| 157 static_cast<AVDACodecImage*>(image.get()) | 149 static_cast<AVDACodecImage*>(image.get()) |
| 158 ->SetTexture(texture_ref->texture()); | 150 ->set_texture(texture_ref->texture()); |
| 159 } else { | 151 } else { |
| 160 // Clear the unowned service_id, so that this texture is no longer going | 152 // Clear the unowned service_id, so that this texture is no longer going |
| 161 // to depend on the surface texture at all. | 153 // to depend on the surface texture at all. |
| 162 texture_ref->texture()->SetUnownedServiceId(0); | 154 texture_ref->texture()->SetUnownedServiceId(0); |
| 163 } | 155 } |
| 164 | 156 |
| 165 // For SurfaceTexture we set the image to UNBOUND so that the implementation | 157 // For SurfaceTexture we set the image to UNBOUND so that the implementation |
| 166 // will call CopyTexImage, which is where AVDACodecImage updates the | 158 // will call CopyTexImage, which is where AVDACodecImage updates the |
| 167 // SurfaceTexture to the right frame. | 159 // SurfaceTexture to the right frame. |
| 168 // For SurfaceView we set the image to be BOUND because ScheduleOverlayPlane | 160 // For SurfaceView we set the image to be BOUND because ScheduleOverlayPlane |
| 169 // expects it. If something tries to sample from this texture it won't work, | 161 // expects it. If something tries to sample from this texture it won't work, |
| 170 // but there's no way to sample from a SurfaceView anyway, so it doesn't | 162 // but there's no way to sample from a SurfaceView anyway, so it doesn't |
| 171 // matter. The only way to use this texture is to schedule it as an overlay. | 163 // matter. The only way to use this texture is to schedule it as an overlay. |
| 172 const gpu::gles2::Texture::ImageState image_state = | 164 const gpu::gles2::Texture::ImageState image_state = |
| 173 surface_texture_ ? gpu::gles2::Texture::UNBOUND | 165 surface_texture_ ? gpu::gles2::Texture::UNBOUND |
| 174 : gpu::gles2::Texture::BOUND; | 166 : gpu::gles2::Texture::BOUND; |
| 175 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), | 167 texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), |
| 176 0, image.get(), image_state); | 168 0, image.get(), image_state); |
| 177 } | 169 } |
| 178 | 170 |
| 179 void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer( | 171 void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer( |
| 180 int32_t codec_buf_index, | 172 int32_t codec_buf_index, |
| 181 const media::PictureBuffer& picture_buffer) { | 173 const media::PictureBuffer& picture_buffer) { |
| 182 // Make sure that the decoder is available. | 174 // Make sure that the decoder is available. |
| 183 RETURN_IF_NULL(state_provider_->GetGlDecoder()); | 175 RETURN_IF_NULL(state_provider_->GetGlDecoder()); |
| 184 | 176 |
| 185 // Notify the AVDACodecImage for picture_buffer that it should use the | 177 // Notify the AVDACodecImage for picture_buffer that it should use the |
| 186 // decoded buffer codec_buf_index to render this frame. | 178 // decoded buffer codec_buf_index to render this frame. |
| 187 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer); | 179 AVDACodecImage* avda_image = |
| 180 shared_state_->GetImageForPicture(picture_buffer.id()); |
| 188 RETURN_IF_NULL(avda_image); | 181 RETURN_IF_NULL(avda_image); |
| 189 DCHECK_EQ(avda_image->GetMediaCodecBufferIndex(), -1); | 182 |
| 190 // Note that this is not a race, since we do not re-use a PictureBuffer | 183 // Note that this is not a race, since we do not re-use a PictureBuffer |
| 191 // until after the CC is done drawing it. | 184 // until after the CC is done drawing it. |
| 192 avda_image->SetMediaCodecBufferIndex(codec_buf_index); | 185 pictures_out_for_display_.push_back(picture_buffer.id()); |
| 193 avda_image->SetSize(state_provider_->GetSize()); | 186 avda_image->set_media_codec_buffer_index(codec_buf_index); |
| 187 avda_image->set_size(state_provider_->GetSize()); |
| 188 |
| 189 MaybeRenderEarly(); |
| 194 } | 190 } |
| 195 | 191 |
| 196 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( | 192 void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer( |
| 197 const media::PictureBuffer& picture_buffer, | 193 const media::PictureBuffer& picture_buffer, |
| 198 bool have_context) { | 194 bool have_context) { |
| 199 // Attach a GLImage to each texture that will use the surface texture. | 195 // Attach a GLImage to each texture that will use the surface texture. |
| 200 // We use a refptr here in case SetImageForPicture fails. | 196 // We use a refptr here in case SetImageForPicture fails. |
| 201 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = | 197 scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = |
| 202 new AVDACodecImage(shared_state_, media_codec_, | 198 new AVDACodecImage(picture_buffer.id(), shared_state_, media_codec_, |
| 203 state_provider_->GetGlDecoder(), surface_texture_); | 199 state_provider_->GetGlDecoder(), surface_texture_); |
| 204 SetImageForPicture(picture_buffer, gl_image); | 200 SetImageForPicture(picture_buffer, gl_image); |
| 205 | 201 |
| 206 if (!surface_texture_ && have_context) { | 202 if (!surface_texture_ && have_context) { |
| 207 // To make devtools work, we're using a 2D texture. Make it transparent, | 203 // 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 | 204 // 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. | 205 // because devtools draws and reads back, which skips overlay processing. |
| 210 // It's unclear why devtools renders twice -- once normally, and once | 206 // It's unclear why devtools renders twice -- once normally, and once |
| 211 // including a readback layer. The result is that the device screen | 207 // including a readback layer. The result is that the device screen |
| 212 // flashes as we alternately draw the overlay hole and this texture, | 208 // flashes as we alternately draw the overlay hole and this texture, |
| 213 // unless we make the texture transparent. | 209 // unless we make the texture transparent. |
| 214 static const uint8_t rgba[] = {0, 0, 0, 0}; | 210 static const uint8_t rgba[] = {0, 0, 0, 0}; |
| 215 const gfx::Size size(1, 1); | 211 const gfx::Size size(1, 1); |
| 216 DCHECK_LE(1u, picture_buffer.texture_ids().size()); | 212 DCHECK_LE(1u, picture_buffer.texture_ids().size()); |
| 217 glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]); | 213 glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]); |
| 218 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, | 214 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
| 219 GL_RGBA, GL_UNSIGNED_BYTE, rgba); | 215 GL_RGBA, GL_UNSIGNED_BYTE, rgba); |
| 220 } | 216 } |
| 221 } | 217 } |
| 222 | 218 |
| 223 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture( | 219 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture( |
| 224 const media::PictureBuffer& picture_buffer) { | 220 const media::PictureBuffer& picture_buffer) { |
| 225 AVDACodecImage* avda_image = GetImageForPicture(picture_buffer); | 221 AVDACodecImage* avda_image = |
| 226 | 222 shared_state_->GetImageForPicture(picture_buffer.id()); |
| 227 // See if there is a media codec buffer still attached to this image. | 223 RETURN_IF_NULL(avda_image); |
| 228 const int32_t codec_buffer = avda_image->GetMediaCodecBufferIndex(); | 224 avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); |
| 229 | |
| 230 if (codec_buffer >= 0) { | |
| 231 // PictureBuffer wasn't displayed, so release the buffer. | |
| 232 media_codec_->ReleaseOutputBuffer(codec_buffer, false); | |
| 233 avda_image->SetMediaCodecBufferIndex(-1); | |
| 234 } | |
| 235 } | 225 } |
| 236 | 226 |
| 237 void AndroidDeferredRenderingBackingStrategy::ReuseOnePictureBuffer( | 227 void AndroidDeferredRenderingBackingStrategy::ReuseOnePictureBuffer( |
| 238 const media::PictureBuffer& picture_buffer) { | 228 const media::PictureBuffer& picture_buffer) { |
| 229 pictures_out_for_display_.erase( |
| 230 std::remove(pictures_out_for_display_.begin(), |
| 231 pictures_out_for_display_.end(), picture_buffer.id()), |
| 232 pictures_out_for_display_.end()); |
| 233 |
| 239 // At this point, the CC must be done with the picture. We can't really | 234 // 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, | 235 // 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 | 236 // when it waits on the sync point before releasing the mailbox. That sync |
| 242 // point is inserted by destroying the resource in VideoLayerImpl::DidDraw. | 237 // point is inserted by destroying the resource in VideoLayerImpl::DidDraw. |
| 243 ReleaseCodecBufferForPicture(picture_buffer); | 238 ReleaseCodecBufferForPicture(picture_buffer); |
| 239 MaybeRenderEarly(); |
| 240 } |
| 241 |
| 242 void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBuffers( |
| 243 const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) { |
| 244 for (const std::pair<int, media::PictureBuffer>& entry : buffers) |
| 245 ReleaseCodecBufferForPicture(entry.second); |
| 246 } |
| 247 |
| 248 void AndroidDeferredRenderingBackingStrategy::MaybeRenderEarly() { |
| 249 if (pictures_out_for_display_.empty()) |
| 250 return; |
| 251 |
| 252 // See if we can consume the front buffer / render to the SurfaceView. Iterate |
| 253 // in reverse to find the most recent front buffer. If none is found, the |
| 254 // |front_index| will point to the beginning of the array. |
| 255 size_t front_index = pictures_out_for_display_.size() - 1; |
| 256 AVDACodecImage* first_renderable_image = nullptr; |
| 257 for (int i = front_index; i >= 0; --i) { |
| 258 const int id = pictures_out_for_display_[i]; |
| 259 AVDACodecImage* avda_image = shared_state_->GetImageForPicture(id); |
| 260 if (!avda_image) |
| 261 continue; |
| 262 |
| 263 // Update the front buffer index as we move along to shorten the number of |
| 264 // candidate images we look at for back buffer rendering. |
| 265 front_index = i; |
| 266 first_renderable_image = avda_image; |
| 267 |
| 268 // If we find a front buffer, stop and indicate that front buffer rendering |
| 269 // is not possible since another image is already in the front buffer. |
| 270 if (avda_image->was_rendered_to_front_buffer()) { |
| 271 first_renderable_image = nullptr; |
| 272 break; |
| 273 } |
| 274 } |
| 275 |
| 276 if (first_renderable_image) { |
| 277 first_renderable_image->UpdateSurface( |
| 278 AVDACodecImage::UpdateMode::RENDER_TO_FRONT_BUFFER); |
| 279 } |
| 280 |
| 281 // Back buffer rendering is only available for surface textures. We'll always |
| 282 // have at least one front buffer, so the next buffer must be the backbuffer. |
| 283 size_t backbuffer_index = front_index + 1; |
| 284 if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size()) |
| 285 return; |
| 286 |
| 287 // See if the back buffer is free. If so, then render the frame adjacent to |
| 288 // the front buffer. The listing is in render order, so we can just use the |
| 289 // first unrendered frame if there is back buffer space. |
| 290 first_renderable_image = shared_state_->GetImageForPicture( |
| 291 pictures_out_for_display_[backbuffer_index]); |
| 292 if (!first_renderable_image || |
| 293 first_renderable_image->was_rendered_to_back_buffer()) { |
| 294 return; |
| 295 } |
| 296 |
| 297 // Due to the loop in the beginning this should never be true. |
| 298 DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); |
| 299 first_renderable_image->UpdateSurface( |
| 300 AVDACodecImage::UpdateMode::RENDER_TO_BACK_BUFFER); |
| 244 } | 301 } |
| 245 | 302 |
| 246 void AndroidDeferredRenderingBackingStrategy::CodecChanged( | 303 void AndroidDeferredRenderingBackingStrategy::CodecChanged( |
| 247 media::VideoCodecBridge* codec, | 304 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; | 305 media_codec_ = codec; |
| 252 for (const std::pair<int, media::PictureBuffer>& entry : buffers) { | 306 shared_state_->CodecChanged(codec); |
| 253 AVDACodecImage* avda_image = GetImageForPicture(entry.second); | |
| 254 avda_image->SetMediaCodec(codec); | |
| 255 avda_image->SetMediaCodecBufferIndex(-1); | |
| 256 } | |
| 257 } | 307 } |
| 258 | 308 |
| 259 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { | 309 void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() { |
| 260 shared_state_->SignalFrameAvailable(); | 310 shared_state_->SignalFrameAvailable(); |
| 261 } | 311 } |
| 262 | 312 |
| 263 bool AndroidDeferredRenderingBackingStrategy::ArePicturesOverlayable() { | 313 bool AndroidDeferredRenderingBackingStrategy::ArePicturesOverlayable() { |
| 264 // SurfaceView frames are always overlayable because that's the only way to | 314 // SurfaceView frames are always overlayable because that's the only way to |
| 265 // display them. | 315 // display them. |
| 266 return !surface_texture_; | 316 return !surface_texture_; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 296 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id); | 346 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id); |
| 297 // The target texture's size will exactly match the source. | 347 // The target texture's size will exactly match the source. |
| 298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 350 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); | 351 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, | 352 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
| 303 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); | 353 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
| 304 } | 354 } |
| 305 | 355 |
| 306 | |
| 307 | |
| 308 float transform_matrix[16]; | 356 float transform_matrix[16]; |
| 309 surface_texture_->GetTransformMatrix(transform_matrix); | 357 surface_texture_->GetTransformMatrix(transform_matrix); |
| 310 | 358 |
| 311 gpu::CopyTextureCHROMIUMResourceManager copier; | 359 gpu::CopyTextureCHROMIUMResourceManager copier; |
| 312 copier.Initialize( | 360 copier.Initialize( |
| 313 gl_decoder, | 361 gl_decoder, |
| 314 gl_decoder->GetContextGroup()->feature_info()->feature_flags()); | 362 gl_decoder->GetContextGroup()->feature_info()->feature_flags()); |
| 315 copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES, | 363 copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES, |
| 316 shared_state_->surface_texture_service_id(), | 364 shared_state_->surface_texture_service_id(), |
| 317 GL_TEXTURE_2D, tmp_texture_id, size.width(), | 365 GL_TEXTURE_2D, tmp_texture_id, size.width(), |
| (...skipping 23 matching lines...) Expand all Loading... |
| 341 continue; | 389 continue; |
| 342 gfx::ScopedTextureBinder texture_binder( | 390 gfx::ScopedTextureBinder texture_binder( |
| 343 GL_TEXTURE_EXTERNAL_OES, texture_ref->texture()->service_id()); | 391 GL_TEXTURE_EXTERNAL_OES, texture_ref->texture()->service_id()); |
| 344 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); | 392 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); |
| 345 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 393 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 346 } | 394 } |
| 347 | 395 |
| 348 EGLBoolean result = | 396 EGLBoolean result = |
| 349 eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), egl_image); | 397 eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), egl_image); |
| 350 if (result == EGL_FALSE) { | 398 if (result == EGL_FALSE) { |
| 351 DLOG(ERROR) << "Error destroying EGLImage: " | 399 DLOG(ERROR) << "Error destroying EGLImage: " << ui::GetLastEGLErrorString(); |
| 352 << ui::GetLastEGLErrorString(); | |
| 353 } | 400 } |
| 354 } | 401 } |
| 355 | 402 |
| 356 bool AndroidDeferredRenderingBackingStrategy::DoesSurfaceTextureDetachWork() | 403 bool AndroidDeferredRenderingBackingStrategy::DoesSurfaceTextureDetachWork() |
| 357 const { | 404 const { |
| 358 bool surface_texture_detach_works = true; | 405 bool surface_texture_detach_works = true; |
| 359 if (gpu::gles2::GLES2Decoder* gl_decoder = | 406 if (gpu::gles2::GLES2Decoder* gl_decoder = |
| 360 state_provider_->GetGlDecoder().get()) { | 407 state_provider_->GetGlDecoder().get()) { |
| 361 if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) { | 408 if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) { |
| 362 if (gpu::gles2::FeatureInfo* feature_info = group->feature_info()) { | 409 if (gpu::gles2::FeatureInfo* feature_info = group->feature_info()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 380 } | 427 } |
| 381 } | 428 } |
| 382 | 429 |
| 383 return surface_texture_detach_works; | 430 return surface_texture_detach_works; |
| 384 } | 431 } |
| 385 | 432 |
| 386 bool AndroidDeferredRenderingBackingStrategy::ShouldCopyPictures() const { | 433 bool AndroidDeferredRenderingBackingStrategy::ShouldCopyPictures() const { |
| 387 // Mali + <= KitKat crashes when we try to do this. We don't know if it's | 434 // Mali + <= KitKat crashes when we try to do this. We don't know if it's |
| 388 // due to detaching a surface texture, but it's the same set of devices. | 435 // due to detaching a surface texture, but it's the same set of devices. |
| 389 if (!DoesSurfaceTextureDetachWork()) | 436 if (!DoesSurfaceTextureDetachWork()) |
| 390 return false; | 437 return false; |
| 391 | 438 |
| 392 // Other devices are unreliable for other reasons (e.g., EGLImage). | 439 // Other devices are unreliable for other reasons (e.g., EGLImage). |
| 393 if (gpu::gles2::GLES2Decoder* gl_decoder = | 440 if (gpu::gles2::GLES2Decoder* gl_decoder = |
| 394 state_provider_->GetGlDecoder().get()) { | 441 state_provider_->GetGlDecoder().get()) { |
| 395 if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) { | 442 if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) { |
| 396 if (gpu::gles2::FeatureInfo* feature_info = group->feature_info()) { | 443 if (gpu::gles2::FeatureInfo* feature_info = group->feature_info()) { |
| 397 return !feature_info->workarounds().avda_dont_copy_pictures; | 444 return !feature_info->workarounds().avda_dont_copy_pictures; |
| 398 } | 445 } |
| 399 } | 446 } |
| 400 } | 447 } |
| 401 | 448 |
| 402 // Samsung Galaxy Tab A, J3, and J1 Mini all like to crash on Lollipop in | 449 // Samsung Galaxy Tab A, J3, and J1 Mini all like to crash on Lollipop in |
| 403 // glEGLImageTargetTexture2DOES . Exact models were SM-T280, SM-J320F, | 450 // glEGLImageTargetTexture2DOES . Exact models were SM-T280, SM-J320F, |
| 404 // and SM-j105H. | 451 // and SM-j105H. |
| 405 if (base::android::BuildInfo::GetInstance()->sdk_int() <= 22) { // L MR1 | 452 if (base::android::BuildInfo::GetInstance()->sdk_int() <= 22) { // L MR1 |
| 406 const std::string brand( | 453 const std::string brand( |
| 407 base::ToLowerASCII(base::android::BuildInfo::GetInstance()->brand())); | 454 base::ToLowerASCII(base::android::BuildInfo::GetInstance()->brand())); |
| 408 if (brand == "samsung") { | 455 if (brand == "samsung") { |
| 409 const std::string model( | 456 const std::string model( |
| 410 base::ToLowerASCII(base::android::BuildInfo::GetInstance()->model())); | 457 base::ToLowerASCII(base::android::BuildInfo::GetInstance()->model())); |
| 411 if (model.find("sm-t280") != std::string::npos || | 458 if (model.find("sm-t280") != std::string::npos || |
| 412 model.find("sm-j320f") != std::string::npos || | 459 model.find("sm-j320f") != std::string::npos || |
| 413 model.find("sm-j105") != std::string::npos) | 460 model.find("sm-j105") != std::string::npos) |
| 414 return false; | 461 return false; |
| 415 } | 462 } |
| 416 } | 463 } |
| 417 | 464 |
| 418 // Assume so. | 465 // Assume so. |
| 419 return true; | 466 return true; |
| 420 } | 467 } |
| 421 | 468 |
| 422 } // namespace content | 469 } // namespace content |
| OLD | NEW |