OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
Ami GONE FROM CHROMIUM
2012/11/14 01:26:07
CL description needs update.
ananta
2012/11/14 03:05:42
Done.
| |
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/dxva_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" |
6 | 6 |
7 #if !defined(OS_WIN) | 7 #if !defined(OS_WIN) |
8 #error This file should only be built on Windows. | 8 #error This file should only be built on Windows. |
9 #endif // !defined(OS_WIN) | 9 #endif // !defined(OS_WIN) |
10 | 10 |
11 #include <ks.h> | 11 #include <ks.h> |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 StopOnError(error_code); \ | 66 StopOnError(error_code); \ |
67 return ret; \ | 67 return ret; \ |
68 } \ | 68 } \ |
69 } while (0) | 69 } while (0) |
70 | 70 |
71 #define RETURN_AND_NOTIFY_ON_HR_FAILURE(result, log, error_code, ret) \ | 71 #define RETURN_AND_NOTIFY_ON_HR_FAILURE(result, log, error_code, ret) \ |
72 RETURN_AND_NOTIFY_ON_FAILURE(SUCCEEDED(result), \ | 72 RETURN_AND_NOTIFY_ON_FAILURE(SUCCEEDED(result), \ |
73 log << ", HRESULT: 0x" << std::hex << result, \ | 73 log << ", HRESULT: 0x" << std::hex << result, \ |
74 error_code, ret); | 74 error_code, ret); |
75 | 75 |
76 // Maximum number of iterations we allow before aborting the attempt to flush | |
77 // the batched queries to the driver. | |
78 enum { kMaxIterationsForD3DFlush = 10 }; | |
79 | |
76 static IMFSample* CreateEmptySample() { | 80 static IMFSample* CreateEmptySample() { |
77 base::win::ScopedComPtr<IMFSample> sample; | 81 base::win::ScopedComPtr<IMFSample> sample; |
78 HRESULT hr = MFCreateSample(sample.Receive()); | 82 HRESULT hr = MFCreateSample(sample.Receive()); |
79 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); | 83 RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL); |
80 return sample.Detach(); | 84 return sample.Detach(); |
81 } | 85 } |
82 | 86 |
83 // Creates a Media Foundation sample with one buffer of length |buffer_length| | 87 // Creates a Media Foundation sample with one buffer of length |buffer_length| |
84 // on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0. | 88 // on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0. |
85 static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) { | 89 static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) { |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
389 NULL, | 393 NULL, |
390 d3d_surface, | 394 d3d_surface, |
391 NULL, | 395 NULL, |
392 D3DTEXF_NONE); | 396 D3DTEXF_NONE); |
393 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", | 397 RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed", |
394 false); | 398 false); |
395 // Ideally, this should be done immediately before the draw call that uses | 399 // Ideally, this should be done immediately before the draw call that uses |
396 // the texture. Flush it once here though. | 400 // the texture. Flush it once here though. |
397 hr = query_->Issue(D3DISSUE_END); | 401 hr = query_->Issue(D3DISSUE_END); |
398 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false); | 402 RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false); |
399 do { | 403 |
400 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH); | 404 // The DXVA decoder has its own device which it uses for decoding. ANGLE |
401 if (hr == S_FALSE) | 405 // has its own device which we don't have access to. |
402 Sleep(1); // Poor-man's Yield(). | 406 // The above code attempts to copy the decoded picture into a surface |
403 } while (hr == S_FALSE); | 407 // which is owned by ANGLE. As there are multiple devices involved in |
408 // this, the StretchRect call above is not synchronous. | |
409 // We attempt to flush the batched operations to ensure that the picture is | |
410 // copied to the surface owned by ANGLE. | |
411 // We need to do this in a loop and call flush multiple times. | |
412 // However we have seen the GetData call for flushing the operations fail | |
413 // to return success on some intel/ATI GPU drivers thus resulting in an | |
414 // infinite loop. | |
415 // Workaround is to have a limit of 10 on the number of iterations for | |
416 // flushing and if we reach the upper limit, we force a readback from | |
417 // the ANGLE surface to a temporary surface created in system memory which | |
418 // ensures that the pending operations on the ANGLE surface complete. | |
Ami GONE FROM CHROMIUM
2012/11/14 01:26:07
s/complete/completes/
ananta
2012/11/14 03:05:42
Rephrased
| |
419 int iterations = 0; | |
420 while ((query_->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE) && | |
421 ++iterations < kMaxIterationsForD3DFlush) { | |
422 Sleep(1); // Poor-man's Yield(). | |
423 } | |
424 | |
425 if (iterations > kMaxIterationsForD3DFlush) { | |
Ami GONE FROM CHROMIUM
2012/11/14 01:26:07
This can never be true.
ananta
2012/11/14 03:05:42
This code has been removed in favor of the BeginFr
| |
426 base::win::ScopedComPtr<IDirect3DSurface9> temp_surface; | |
427 hr = device_->CreateOffscreenPlainSurface(surface_desc.Width, | |
Ami GONE FROM CHROMIUM
2012/11/14 01:26:07
IIUC systems that have this problem exhibit it for
ananta
2012/11/14 03:05:42
Removed.
| |
428 surface_desc.Height, | |
429 D3DFMT_X8R8G8B8, | |
430 D3DPOOL_SYSTEMMEM, | |
431 temp_surface.Receive(), | |
432 NULL); | |
433 RETURN_ON_HR_FAILURE(hr, "Failed to create system offscreen surface", | |
434 false); | |
435 hr = device_->GetRenderTargetData(d3d_surface, temp_surface); | |
apatrick_chromium
2012/11/14 01:27:49
This call could be asynchronous as well (don't kno
ananta
2012/11/14 03:05:42
Code has been removed.
| |
436 RETURN_ON_HR_FAILURE(hr, "Failed to render decoded data to system memory", | |
437 false); | |
438 } | |
404 eglBindTexImage( | 439 eglBindTexImage( |
405 static_cast<EGLDisplay*>(eglGetDisplay(EGL_DEFAULT_DISPLAY)), | 440 static_cast<EGLDisplay*>(eglGetDisplay(EGL_DEFAULT_DISPLAY)), |
406 decoding_surface_, | 441 decoding_surface_, |
407 EGL_BACK_BUFFER); | 442 EGL_BACK_BUFFER); |
408 } else { | 443 } else { |
409 scoped_array<char> bits; | 444 scoped_array<char> bits; |
410 RETURN_ON_FAILURE(GetBitmapFromSurface(DXVAVideoDecodeAccelerator::device_, | 445 RETURN_ON_FAILURE(GetBitmapFromSurface(DXVAVideoDecodeAccelerator::device_, |
411 dest_surface, &bits), | 446 dest_surface, &bits), |
412 "Failed to get bitmap from surface for rendering", | 447 "Failed to get bitmap from surface for rendering", |
413 false); | 448 false); |
(...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1138 return; | 1173 return; |
1139 } | 1174 } |
1140 | 1175 |
1141 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 1176 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
1142 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); | 1177 &DXVAVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); |
1143 | 1178 |
1144 state_ = kNormal; | 1179 state_ = kNormal; |
1145 } | 1180 } |
1146 | 1181 |
1147 } // namespace content | 1182 } // namespace content |
OLD | NEW |