Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Unified Diff: gpu/ipc/service/direct_composition_surface_win.cc

Issue 2809473003: Switch DirectComposition layers to BGRA if overlay allocation fails. (Closed)
Patch Set: post-review changes Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/ipc/service/direct_composition_surface_win.cc
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc
index ac184e96e62625f2d9ebf3fb886cc2998e6d0867..15dd515b6340992039dd8b238859bf98bc53eaeb 100644
--- a/gpu/ipc/service/direct_composition_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -7,6 +7,8 @@
#include <d3d11_1.h>
#include <dcomptypes.h>
+#include <deque>
+
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
@@ -71,6 +73,37 @@ bool SizeContains(const gfx::Size& a, const gfx::Size& b) {
return gfx::Rect(a).Contains(gfx::Rect(b));
}
+// This keeps track of whether the previous 30 frames used Overlays or GPU
+// composition to present.
+class PresentationHistory {
+ public:
+ static const int kPresentsToStore = 30;
+
+ PresentationHistory() {}
+
+ void AddSample(DXGI_FRAME_PRESENTATION_MODE mode) {
+ if (mode == DXGI_FRAME_PRESENTATION_MODE_COMPOSED)
+ composed_count_++;
+
+ presents_.push_back(mode);
+ if (presents_.size() > kPresentsToStore) {
+ DXGI_FRAME_PRESENTATION_MODE first_mode = presents_.front();
+ if (first_mode == DXGI_FRAME_PRESENTATION_MODE_COMPOSED)
+ composed_count_--;
+ presents_.pop_front();
+ }
+ }
+
+ bool valid() const { return presents_.size() >= kPresentsToStore; }
+ int composed_count() const { return composed_count_; }
+
+ private:
+ std::deque<DXGI_FRAME_PRESENTATION_MODE> presents_;
+ int composed_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(PresentationHistory);
+};
+
// Only one DirectComposition surface can be rendered into at a time. Track
// here which IDCompositionSurface is being rendered into. If another context
// is made current, then this surface will be suspended.
@@ -178,7 +211,8 @@ class DCLayerTree::SwapChainPresenter {
// Returns true if the video processor changed.
bool InitializeVideoProcessor(const gfx::Size& in_size,
const gfx::Size& out_size);
- void ReallocateSwapChain();
+ void ReallocateSwapChain(bool yuy2);
+ bool ShouldBeYUY2();
DCLayerTree* surface_;
PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_;
@@ -193,6 +227,10 @@ class DCLayerTree::SwapChainPresenter {
float swap_chain_scale_x_ = 0.0f;
float swap_chain_scale_y_ = 0.0f;
+ PresentationHistory presentation_history_;
+ bool failed_to_create_yuy2_swapchain_ = false;
+ int frames_since_color_space_change_ = 0;
+
// This is the GLImage that was presented in the last frame.
scoped_refptr<gl::GLImageDXGI> last_gl_image_;
@@ -287,6 +325,25 @@ DCLayerTree::SwapChainPresenter::SwapChainPresenter(
DCLayerTree::SwapChainPresenter::~SwapChainPresenter() {}
+bool DCLayerTree::SwapChainPresenter::ShouldBeYUY2() {
+ // Start out as YUY2.
+ if (!presentation_history_.valid())
+ return true;
+ int composition_count = presentation_history_.composed_count();
+
+ // It's more efficient to use a BGRA backbuffer instead of YUY2 if overlays
+ // aren't being used, as otherwise DWM will use the video processor a second
+ // time to convert it to BGRA before displaying it on screen.
+
+ if (is_yuy2_swapchain_) {
+ // Switch to BGRA once 3/4 of presents are composed.
+ return composition_count < (PresentationHistory::kPresentsToStore * 3 / 4);
+ } else {
+ // Switch to YUY2 once 3/4 are using overlays (or unknown).
+ return composition_count < (PresentationHistory::kPresentsToStore / 4);
+ }
+}
+
void DCLayerTree::SwapChainPresenter::PresentToSwapChain(
const ui::DCRendererLayerParams& params) {
gl::GLImageDXGI* image_dxgi =
@@ -309,12 +366,15 @@ void DCLayerTree::SwapChainPresenter::PresentToSwapChain(
InitializeVideoProcessor(ceiled_input_size, swap_chain_size);
+ bool yuy2_swapchain = ShouldBeYUY2();
bool first_present = false;
- if (!swap_chain_ || swap_chain_size_ != swap_chain_size) {
+ if (!swap_chain_ || swap_chain_size_ != swap_chain_size ||
+ ((yuy2_swapchain != is_yuy2_swapchain_) &&
+ !failed_to_create_yuy2_swapchain_)) {
first_present = true;
swap_chain_size_ = swap_chain_size;
swap_chain_.Reset();
- ReallocateSwapChain();
+ ReallocateSwapChain(yuy2_swapchain);
} else if (last_gl_image_ == image_dxgi) {
// The swap chain is presenting the same image as last swap, which means
// that the image was never returned to the video decoder and should have
@@ -415,12 +475,15 @@ void DCLayerTree::SwapChainPresenter::PresentToSwapChain(
swap_chain_->Present(first_present ? 0 : 1, 0);
+ frames_since_color_space_change_++;
+
base::win::ScopedComPtr<IDXGISwapChainMedia> swap_chain_media;
if (SUCCEEDED(swap_chain_.QueryInterface(swap_chain_media.Receive()))) {
DXGI_FRAME_STATISTICS_MEDIA stats = {};
if (SUCCEEDED(swap_chain_media->GetFrameStatisticsMedia(&stats))) {
UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.DirectComposition.CompositionMode",
stats.CompositionMode);
+ presentation_history_.AddSample(stats.CompositionMode);
}
}
}
@@ -443,7 +506,7 @@ bool DCLayerTree::SwapChainPresenter::InitializeVideoProcessor(
return true;
}
-void DCLayerTree::SwapChainPresenter::ReallocateSwapChain() {
+void DCLayerTree::SwapChainPresenter::ReallocateSwapChain(bool yuy2) {
TRACE_EVENT0("gpu", "DCLayerTree::SwapChainPresenter::ReallocateSwapChain");
DCHECK(!swap_chain_);
@@ -475,19 +538,31 @@ void DCLayerTree::SwapChainPresenter::ReallocateSwapChain() {
&handle);
swap_chain_handle_.Set(handle);
- is_yuy2_swapchain_ = true;
+ if (is_yuy2_swapchain_ != yuy2) {
+ UMA_HISTOGRAM_COUNTS_1000(
+ "GPU.DirectComposition.FramesSinceColorSpaceChange",
+ frames_since_color_space_change_);
+ }
+
+ frames_since_color_space_change_ = 0;
+
+ is_yuy2_swapchain_ = false;
// The composition surface handle isn't actually used, but
// CreateSwapChainForComposition can't create YUY2 swapchains.
- HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle(
- d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr,
- swap_chain_.Receive());
-
- if (FAILED(hr)) {
- // This should not be hit in production but is a simple fallback for
- // testing on systems without YUY2 swapchain support.
- DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr
- << ". Falling back to BGRA";
- is_yuy2_swapchain_ = false;
+ HRESULT hr = E_FAIL;
+ if (yuy2) {
+ hr = media_factory->CreateSwapChainForCompositionSurfaceHandle(
+ d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr,
+ swap_chain_.Receive());
+ is_yuy2_swapchain_ = SUCCEEDED(hr);
+ failed_to_create_yuy2_swapchain_ = !is_yuy2_swapchain_;
+ }
+
+ if (!is_yuy2_swapchain_) {
+ if (yuy2) {
+ DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr
+ << ". Falling back to BGRA";
+ }
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.Flags = 0;
hr = media_factory->CreateSwapChainForCompositionSurfaceHandle(
« no previous file with comments | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698