Commit 4f646165 authored by mazda@chromium.org's avatar mazda@chromium.org

Support copying a partial rectangle region from the compositing surface on Win.

BUG=118571
TEST=Manual


Review URL: https://chromiumcodereview.appspot.com/10829054

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148889 0039d316-1c4b-4281-b951-d872f2087c98
parent 1d65f485
......@@ -503,14 +503,8 @@ void RenderWidgetHostImpl::CopyFromBackingStore(
if (view_ && is_accelerated_compositing_active_) {
TRACE_EVENT0("browser",
"RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
#if defined(USE_AURA) || defined(OS_LINUX) || defined(OS_MACOSX)
gfx::Rect copy_rect = src_subrect.IsEmpty() ?
gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
#else
// Just passes an empty rect to CopyFromCompositingSurface on non-Aura Win
// because copying a partial rectangle is not supported.
gfx::Rect copy_rect;
#endif
view_->CopyFromCompositingSurface(copy_rect,
accelerated_dst_size,
callback,
......
......@@ -1199,13 +1199,6 @@ void RenderWidgetHostViewWin::CopyFromCompositingSurface(
const base::Callback<void(bool)>& callback,
skia::PlatformCanvas* output) {
base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
// TODO(mazda): Support copying a partial rectangle from the compositing
// surface with |src_subrect| (http://crbug.com/118571).
if (!src_subrect.IsEmpty()) {
NOTIMPLEMENTED();
return;
}
if (!accelerated_surface_.get())
return;
......@@ -1216,7 +1209,9 @@ void RenderWidgetHostViewWin::CopyFromCompositingSurface(
return;
const bool result = accelerated_surface_->CopyTo(
dst_size, output->getTopDevice()->accessBitmap(true).getPixels());
src_subrect,
dst_size,
output->getTopDevice()->accessBitmap(true).getPixels());
scoped_callback_runner.Release();
callback.Run(result);
}
......
......@@ -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() {
......
......@@ -18,6 +18,10 @@
class PresentThread;
namespace gfx {
class Rect;
}
class SURFACE_EXPORT AcceleratedPresenter
: public base::RefCountedThreadSafe<AcceleratedPresenter> {
public:
......@@ -52,7 +56,9 @@ class SURFACE_EXPORT AcceleratedPresenter
// The public member functions are called on the main thread.
bool Present(HDC dc);
bool CopyTo(const gfx::Size& size, void* buf);
bool CopyTo(const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
void* buf);
void Invalidate();
private:
......@@ -115,11 +121,14 @@ class SURFACE_EXPORT AcceleratedSurface {
// Synchronously present a frame with no acknowledgement.
bool Present(HDC dc);
// Copies the surface data to |buf|. The image data is transformed so that it
// fits in |size|.
// Copies the surface data to |buf|. The copied region is specified with
// |src_subrect| and the image data is transformed so that it fits in
// |dst_size|.
// Caller must ensure that |buf| is allocated with the size no less than
// |4 * size.width() * size.height()| bytes.
bool CopyTo(const gfx::Size& size, void* buf);
// |4 * dst_size.width() * dst_size.height()| bytes.
bool CopyTo(const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
void* buf);
// Temporarily release resources until a new surface is asynchronously
// presented. Present will not be able to represent the last surface after
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment