Index: ui/surface/accelerated_surface_win.cc |
diff --git a/ui/surface/accelerated_surface_win.cc b/ui/surface/accelerated_surface_win.cc |
index 51e2d6125329add171b02b40f32764bea7cfeedf..698f5fcd3d3dbb53c5c241514b1bb8c9de93187c 100644 |
--- a/ui/surface/accelerated_surface_win.cc |
+++ b/ui/surface/accelerated_surface_win.cc |
@@ -25,6 +25,7 @@ |
#include "base/tracked_objects.h" |
#include "base/win/wrapped_window_proc.h" |
#include "ui/base/win/hwnd_util.h" |
+#include "ui/gfx/rect.h" |
#include "ui/gl/gl_switches.h" |
namespace { |
@@ -117,19 +118,27 @@ UINT GetPresentationInterval() { |
return D3DPRESENT_INTERVAL_ONE; |
} |
-// Calculate the number necessary to transform |source_size| into |dest_size| |
-// by repeating downsampling of the image of |source_size| by a factor no more |
+// Calculate the number necessary to transform |src_subrect| into |dst_size| |
+// by repeating downsampling of the image of |src_subrect| by a factor no more |
// than 2. |
-int GetResampleCount(const gfx::Size& source_size, const gfx::Size& dest_size) { |
+int GetResampleCount(const gfx::Rect& src_subrect, |
+ const gfx::Size& dst_size, |
+ const gfx::Size& back_buffer_size) { |
+ if (src_subrect.size() == dst_size) { |
+ // Even when the size of |src_subrect| is equal to |dst_size|, it is |
+ // necessary to resample pixels at least once unless |src_subrect| exactly |
+ // covers the back buffer. |
+ return (src_subrect == gfx::Rect(back_buffer_size)) ? 0 : 1; |
+ } |
int width_count = 0; |
- int width = source_size.width(); |
- while (width > dest_size.width()) { |
+ int width = src_subrect.width(); |
+ while (width > dst_size.width()) { |
++width_count; |
width >>= 1; |
} |
int height_count = 0; |
- int height = source_size.height(); |
- while (height > dest_size.height()) { |
+ int height = src_subrect.height(); |
+ while (height > dst_size.height()) { |
++height_count; |
height >>= 1; |
} |
@@ -506,7 +515,9 @@ bool AcceleratedPresenter::DoRealPresent(HDC dc) |
return true; |
} |
-bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) { |
+bool AcceleratedPresenter::CopyTo(const gfx::Rect& src_subrect, |
+ const gfx::Size& dst_size, |
+ void* buf) { |
base::AutoLock locked(lock_); |
if (!swap_chain_) |
@@ -530,18 +541,19 @@ bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) { |
// Set up intermediate buffers needed for downsampling. |
const int resample_count = |
- GetResampleCount(gfx::Size(desc.Width, desc.Height), size); |
+ GetResampleCount(src_subrect, dst_size, back_buffer_size); |
base::win::ScopedComPtr<IDirect3DSurface9> final_surface; |
base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2]; |
if (resample_count == 0) |
final_surface = back_buffer; |
if (resample_count > 0) { |
if (!CreateTemporarySurface(present_thread_->device(), |
- size, |
+ dst_size, |
final_surface.Receive())) |
return false; |
} |
- const gfx::Size half_size = GetHalfSizeNoLessThan(back_buffer_size, size); |
+ const gfx::Size half_size = |
+ GetHalfSizeNoLessThan(src_subrect.size(), dst_size); |
if (resample_count > 1) { |
if (!CreateTemporarySurface(present_thread_->device(), |
half_size, |
@@ -549,17 +561,18 @@ bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) { |
return false; |
} |
if (resample_count > 2) { |
- const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, size); |
+ const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, dst_size); |
if (!CreateTemporarySurface(present_thread_->device(), |
quarter_size, |
temp_buffer[1].Receive())) |
return false; |
} |
+ |
// Repeat downsampling the surface until its size becomes identical to |
- // |size|. We keep the factor of each downsampling no more than two because |
- // using a factor more than two can introduce aliasing. |
- gfx::Size read_size = back_buffer_size; |
+ // |dst_size|. We keep the factor of each downsampling no more than two |
+ // because using a factor more than two can introduce aliasing. |
+ RECT read_rect = src_subrect.ToRECT(); |
gfx::Size write_size = half_size; |
int read_buffer_index = 1; |
int write_buffer_index = 0; |
@@ -569,8 +582,7 @@ bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) { |
base::win::ScopedComPtr<IDirect3DSurface9> write_buffer = |
(i == resample_count - 1) ? final_surface : |
temp_buffer[write_buffer_index]; |
- RECT read_rect = {0, 0, read_size.width(), read_size.height()}; |
- RECT write_rect = {0, 0, write_size.width(), write_size.height()}; |
+ RECT write_rect = gfx::Rect(write_size).ToRECT(); |
hr = present_thread_->device()->StretchRect(read_buffer, |
&read_rect, |
write_buffer, |
@@ -578,18 +590,16 @@ bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) { |
D3DTEXF_LINEAR); |
if (FAILED(hr)) |
return false; |
- read_size = write_size; |
- write_size = GetHalfSizeNoLessThan(write_size, size); |
+ read_rect = write_rect; |
+ write_size = GetHalfSizeNoLessThan(write_size, dst_size); |
std::swap(read_buffer_index, write_buffer_index); |
} |
- DCHECK(size == read_size); |
- |
base::win::ScopedComPtr<IDirect3DSurface9> temp_surface; |
HANDLE handle = reinterpret_cast<HANDLE>(buf); |
hr = present_thread_->device()->CreateOffscreenPlainSurface( |
- size.width(), |
- size.height(), |
+ dst_size.width(), |
+ dst_size.height(), |
D3DFMT_A8R8G8B8, |
D3DPOOL_SYSTEMMEM, |
temp_surface.Receive(), |
@@ -847,8 +857,10 @@ bool AcceleratedSurface::Present(HDC dc) { |
return presenter_->Present(dc); |
} |
-bool AcceleratedSurface::CopyTo(const gfx::Size& size, void* buf) { |
- return presenter_->CopyTo(size, buf); |
+bool AcceleratedSurface::CopyTo(const gfx::Rect& src_subrect, |
+ const gfx::Size& dst_size, |
+ void* buf) { |
+ return presenter_->CopyTo(src_subrect, dst_size, buf); |
} |
void AcceleratedSurface::Suspend() { |