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

Side by Side Diff: ui/surface/accelerated_surface_win.cc

Issue 10829054: Support copying a partial rectangle region from the compositing surface on Win. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comment Created 8 years, 4 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/surface/accelerated_surface_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ui/surface/accelerated_surface_win.h" 5 #include "ui/surface/accelerated_surface_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <algorithm> 8 #include <algorithm>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h" 14 #include "base/debug/trace_event.h"
15 #include "base/file_path.h" 15 #include "base/file_path.h"
16 #include "base/lazy_instance.h" 16 #include "base/lazy_instance.h"
17 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
18 #include "base/scoped_native_library.h" 18 #include "base/scoped_native_library.h"
19 #include "base/string_number_conversions.h" 19 #include "base/string_number_conversions.h"
20 #include "base/stringprintf.h" 20 #include "base/stringprintf.h"
21 #include "base/synchronization/waitable_event.h" 21 #include "base/synchronization/waitable_event.h"
22 #include "base/threading/thread.h" 22 #include "base/threading/thread.h"
23 #include "base/threading/thread_restrictions.h" 23 #include "base/threading/thread_restrictions.h"
24 #include "base/time.h" 24 #include "base/time.h"
25 #include "base/tracked_objects.h" 25 #include "base/tracked_objects.h"
26 #include "base/win/wrapped_window_proc.h" 26 #include "base/win/wrapped_window_proc.h"
27 #include "ui/base/win/hwnd_util.h" 27 #include "ui/base/win/hwnd_util.h"
28 #include "ui/gfx/rect.h"
28 #include "ui/gl/gl_switches.h" 29 #include "ui/gl/gl_switches.h"
29 30
30 namespace { 31 namespace {
31 32
32 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version, 33 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version,
33 IDirect3D9Ex **d3d); 34 IDirect3D9Ex **d3d);
34 35
35 const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; 36 const wchar_t kD3D9ModuleName[] = L"d3d9.dll";
36 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; 37 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex";
37 38
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 D3DDECL_END() 111 D3DDECL_END()
111 }; 112 };
112 113
113 UINT GetPresentationInterval() { 114 UINT GetPresentationInterval() {
114 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) 115 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
115 return D3DPRESENT_INTERVAL_IMMEDIATE; 116 return D3DPRESENT_INTERVAL_IMMEDIATE;
116 else 117 else
117 return D3DPRESENT_INTERVAL_ONE; 118 return D3DPRESENT_INTERVAL_ONE;
118 } 119 }
119 120
120 // Calculate the number necessary to transform |source_size| into |dest_size| 121 // Calculate the number necessary to transform |src_subrect| into |dst_size|
121 // by repeating downsampling of the image of |source_size| by a factor no more 122 // by repeating downsampling of the image of |src_subrect| by a factor no more
122 // than 2. 123 // than 2.
123 int GetResampleCount(const gfx::Size& source_size, const gfx::Size& dest_size) { 124 int GetResampleCount(const gfx::Rect& src_subrect,
125 const gfx::Size& dst_size,
126 const gfx::Size& back_buffer_size) {
127 if (src_subrect.size() == dst_size) {
128 // Even when the size of |src_subrect| is equal to |dst_size|, it is
129 // necessary to resample pixels at least once unless |src_subrect| exactly
130 // covers the back buffer.
131 return (src_subrect == gfx::Rect(back_buffer_size)) ? 0 : 1;
132 }
124 int width_count = 0; 133 int width_count = 0;
125 int width = source_size.width(); 134 int width = src_subrect.width();
126 while (width > dest_size.width()) { 135 while (width > dst_size.width()) {
127 ++width_count; 136 ++width_count;
128 width >>= 1; 137 width >>= 1;
129 } 138 }
130 int height_count = 0; 139 int height_count = 0;
131 int height = source_size.height(); 140 int height = src_subrect.height();
132 while (height > dest_size.height()) { 141 while (height > dst_size.height()) {
133 ++height_count; 142 ++height_count;
134 height >>= 1; 143 height >>= 1;
135 } 144 }
136 return std::max(width_count, height_count); 145 return std::max(width_count, height_count);
137 } 146 }
138 147
139 // Returns half the size of |size| no smaller than |min_size|. 148 // Returns half the size of |size| no smaller than |min_size|.
140 gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size, 149 gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size,
141 const gfx::Size& min_size) { 150 const gfx::Size& min_size) {
142 return gfx::Size(std::max(min_size.width(), size.width() / 2), 151 return gfx::Size(std::max(min_size.width(), size.width() / 2),
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 D3DPRESENT_INTERVAL_IMMEDIATE); 508 D3DPRESENT_INTERVAL_IMMEDIATE);
500 // For latency_tests.cc: 509 // For latency_tests.cc:
501 UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete"); 510 UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete");
502 if (FAILED(hr)) 511 if (FAILED(hr))
503 return false; 512 return false;
504 } 513 }
505 514
506 return true; 515 return true;
507 } 516 }
508 517
509 bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) { 518 bool AcceleratedPresenter::CopyTo(const gfx::Rect& src_subrect,
519 const gfx::Size& dst_size,
520 void* buf) {
510 base::AutoLock locked(lock_); 521 base::AutoLock locked(lock_);
511 522
512 if (!swap_chain_) 523 if (!swap_chain_)
513 return false; 524 return false;
514 525
515 base::win::ScopedComPtr<IDirect3DSurface9> back_buffer; 526 base::win::ScopedComPtr<IDirect3DSurface9> back_buffer;
516 HRESULT hr = swap_chain_->GetBackBuffer(0, 527 HRESULT hr = swap_chain_->GetBackBuffer(0,
517 D3DBACKBUFFER_TYPE_MONO, 528 D3DBACKBUFFER_TYPE_MONO,
518 back_buffer.Receive()); 529 back_buffer.Receive());
519 if (FAILED(hr)) 530 if (FAILED(hr))
520 return false; 531 return false;
521 532
522 D3DSURFACE_DESC desc; 533 D3DSURFACE_DESC desc;
523 hr = back_buffer->GetDesc(&desc); 534 hr = back_buffer->GetDesc(&desc);
524 if (FAILED(hr)) 535 if (FAILED(hr))
525 return false; 536 return false;
526 537
527 const gfx::Size back_buffer_size(desc.Width, desc.Height); 538 const gfx::Size back_buffer_size(desc.Width, desc.Height);
528 if (back_buffer_size.IsEmpty()) 539 if (back_buffer_size.IsEmpty())
529 return false; 540 return false;
530 541
531 // Set up intermediate buffers needed for downsampling. 542 // Set up intermediate buffers needed for downsampling.
532 const int resample_count = 543 const int resample_count =
533 GetResampleCount(gfx::Size(desc.Width, desc.Height), size); 544 GetResampleCount(src_subrect, dst_size, back_buffer_size);
534 base::win::ScopedComPtr<IDirect3DSurface9> final_surface; 545 base::win::ScopedComPtr<IDirect3DSurface9> final_surface;
535 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2]; 546 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
536 if (resample_count == 0) 547 if (resample_count == 0)
537 final_surface = back_buffer; 548 final_surface = back_buffer;
538 if (resample_count > 0) { 549 if (resample_count > 0) {
539 if (!CreateTemporarySurface(present_thread_->device(), 550 if (!CreateTemporarySurface(present_thread_->device(),
540 size, 551 dst_size,
541 final_surface.Receive())) 552 final_surface.Receive()))
542 return false; 553 return false;
543 } 554 }
544 const gfx::Size half_size = GetHalfSizeNoLessThan(back_buffer_size, size); 555 const gfx::Size half_size =
556 GetHalfSizeNoLessThan(src_subrect.size(), dst_size);
545 if (resample_count > 1) { 557 if (resample_count > 1) {
546 if (!CreateTemporarySurface(present_thread_->device(), 558 if (!CreateTemporarySurface(present_thread_->device(),
547 half_size, 559 half_size,
548 temp_buffer[0].Receive())) 560 temp_buffer[0].Receive()))
549 return false; 561 return false;
550 } 562 }
551 if (resample_count > 2) { 563 if (resample_count > 2) {
552 const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, size); 564 const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, dst_size);
553 if (!CreateTemporarySurface(present_thread_->device(), 565 if (!CreateTemporarySurface(present_thread_->device(),
554 quarter_size, 566 quarter_size,
555 temp_buffer[1].Receive())) 567 temp_buffer[1].Receive()))
556 return false; 568 return false;
557 } 569 }
558 570
571
559 // Repeat downsampling the surface until its size becomes identical to 572 // Repeat downsampling the surface until its size becomes identical to
560 // |size|. We keep the factor of each downsampling no more than two because 573 // |dst_size|. We keep the factor of each downsampling no more than two
561 // using a factor more than two can introduce aliasing. 574 // because using a factor more than two can introduce aliasing.
562 gfx::Size read_size = back_buffer_size; 575 RECT read_rect = src_subrect.ToRECT();
563 gfx::Size write_size = half_size; 576 gfx::Size write_size = half_size;
564 int read_buffer_index = 1; 577 int read_buffer_index = 1;
565 int write_buffer_index = 0; 578 int write_buffer_index = 0;
566 for (int i = 0; i < resample_count; ++i) { 579 for (int i = 0; i < resample_count; ++i) {
567 base::win::ScopedComPtr<IDirect3DSurface9> read_buffer = 580 base::win::ScopedComPtr<IDirect3DSurface9> read_buffer =
568 (i == 0) ? back_buffer : temp_buffer[read_buffer_index]; 581 (i == 0) ? back_buffer : temp_buffer[read_buffer_index];
569 base::win::ScopedComPtr<IDirect3DSurface9> write_buffer = 582 base::win::ScopedComPtr<IDirect3DSurface9> write_buffer =
570 (i == resample_count - 1) ? final_surface : 583 (i == resample_count - 1) ? final_surface :
571 temp_buffer[write_buffer_index]; 584 temp_buffer[write_buffer_index];
572 RECT read_rect = {0, 0, read_size.width(), read_size.height()}; 585 RECT write_rect = gfx::Rect(write_size).ToRECT();
573 RECT write_rect = {0, 0, write_size.width(), write_size.height()};
574 hr = present_thread_->device()->StretchRect(read_buffer, 586 hr = present_thread_->device()->StretchRect(read_buffer,
575 &read_rect, 587 &read_rect,
576 write_buffer, 588 write_buffer,
577 &write_rect, 589 &write_rect,
578 D3DTEXF_LINEAR); 590 D3DTEXF_LINEAR);
579 if (FAILED(hr)) 591 if (FAILED(hr))
580 return false; 592 return false;
581 read_size = write_size; 593 read_rect = write_rect;
582 write_size = GetHalfSizeNoLessThan(write_size, size); 594 write_size = GetHalfSizeNoLessThan(write_size, dst_size);
583 std::swap(read_buffer_index, write_buffer_index); 595 std::swap(read_buffer_index, write_buffer_index);
584 } 596 }
585 597
586 DCHECK(size == read_size);
587
588 base::win::ScopedComPtr<IDirect3DSurface9> temp_surface; 598 base::win::ScopedComPtr<IDirect3DSurface9> temp_surface;
589 HANDLE handle = reinterpret_cast<HANDLE>(buf); 599 HANDLE handle = reinterpret_cast<HANDLE>(buf);
590 hr = present_thread_->device()->CreateOffscreenPlainSurface( 600 hr = present_thread_->device()->CreateOffscreenPlainSurface(
591 size.width(), 601 dst_size.width(),
592 size.height(), 602 dst_size.height(),
593 D3DFMT_A8R8G8B8, 603 D3DFMT_A8R8G8B8,
594 D3DPOOL_SYSTEMMEM, 604 D3DPOOL_SYSTEMMEM,
595 temp_surface.Receive(), 605 temp_surface.Receive(),
596 &handle); 606 &handle);
597 if (FAILED(hr)) 607 if (FAILED(hr))
598 return false; 608 return false;
599 609
600 // Copy the data in the temporary buffer to the surface backed by |buf|. 610 // Copy the data in the temporary buffer to the surface backed by |buf|.
601 hr = present_thread_->device()->GetRenderTargetData(final_surface, 611 hr = present_thread_->device()->GetRenderTargetData(final_surface,
602 temp_surface); 612 temp_surface);
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 850
841 AcceleratedSurface::~AcceleratedSurface() { 851 AcceleratedSurface::~AcceleratedSurface() {
842 g_accelerated_presenter_map.Pointer()->RemovePresenter(presenter_); 852 g_accelerated_presenter_map.Pointer()->RemovePresenter(presenter_);
843 presenter_->Invalidate(); 853 presenter_->Invalidate();
844 } 854 }
845 855
846 bool AcceleratedSurface::Present(HDC dc) { 856 bool AcceleratedSurface::Present(HDC dc) {
847 return presenter_->Present(dc); 857 return presenter_->Present(dc);
848 } 858 }
849 859
850 bool AcceleratedSurface::CopyTo(const gfx::Size& size, void* buf) { 860 bool AcceleratedSurface::CopyTo(const gfx::Rect& src_subrect,
851 return presenter_->CopyTo(size, buf); 861 const gfx::Size& dst_size,
862 void* buf) {
863 return presenter_->CopyTo(src_subrect, dst_size, buf);
852 } 864 }
853 865
854 void AcceleratedSurface::Suspend() { 866 void AcceleratedSurface::Suspend() {
855 presenter_->Suspend(); 867 presenter_->Suspend();
856 } 868 }
857 869
858 void AcceleratedSurface::WasHidden() { 870 void AcceleratedSurface::WasHidden() {
859 presenter_->WasHidden(); 871 presenter_->WasHidden();
860 } 872 }
OLDNEW
« no previous file with comments | « ui/surface/accelerated_surface_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698