Index: ui/gfx/surface/accelerated_surface_win.cc |
diff --git a/ui/gfx/surface/accelerated_surface_win.cc b/ui/gfx/surface/accelerated_surface_win.cc |
index 45fdf482c3c989f833ae6ffd0242dd8ab5944eb3..49211481fdb657aee195f4c69d004628fc00fccb 100644 |
--- a/ui/gfx/surface/accelerated_surface_win.cc |
+++ b/ui/gfx/surface/accelerated_surface_win.cc |
@@ -107,6 +107,8 @@ class AcceleratedPresenter { |
bool Present(gfx::NativeWindow window); |
+ bool CopyTo(const gfx::Size& size, std::vector<unsigned char>* buf); |
+ |
void Suspend(); |
private: |
@@ -263,6 +265,73 @@ bool AcceleratedPresenter::Present(gfx::NativeWindow window) { |
return true; |
} |
+bool AcceleratedPresenter::CopyTo(const gfx::Size& size, |
+ std::vector<unsigned char>* buf) { |
+ base::win::ScopedComPtr<IDirect3DSurface9> render_target; |
apatrick_chromium
2012/03/07 20:39:37
Make the first line of this function:
base::AutoLo
mazda
2012/03/08 13:14:28
Done.
|
+ HRESULT hr = device_->GetRenderTarget(0, render_target.Receive()); |
apatrick_chromium
2012/03/07 20:39:37
I just changed this unfortunately but you should b
mazda
2012/03/08 13:14:28
Done.
|
+ if (FAILED(hr)) |
+ return false; |
+ |
+ base::win::ScopedComPtr<IDirect3DSurface9> temp_render_target; |
+ hr = device_->CreateRenderTarget( |
+ size.width(), |
+ size.height(), |
+ D3DFMT_A8R8G8B8, |
+ D3DMULTISAMPLE_NONE, |
+ 0, |
+ TRUE, |
+ temp_render_target.Receive(), |
+ NULL); |
+ if (FAILED(hr)) |
+ return false; |
+ |
+ // Copy the render target to a temporary render target first because |
+ // IDirect3DDevice9::StretchRect does not support copying to the surface in |
+ // the system memory. |
+ hr = device_->StretchRect(render_target, NULL, temp_render_target, NULL, |
apatrick_chromium
2012/03/07 20:39:37
If the downsampling reduces the size by more than
mazda
2012/03/08 13:14:28
Done.
|
+ D3DTEXF_LINEAR); |
+ if (FAILED(hr)) |
+ return false; |
+ |
+ base::win::ScopedComPtr<IDirect3DSurface9> temp_surface; |
+ hr = device_->CreateOffscreenPlainSurface( |
+ size.width(), |
+ size.height(), |
+ D3DFMT_A8R8G8B8, |
+ D3DPOOL_SYSTEMMEM, |
+ temp_surface.Receive(), |
+ NULL); |
apatrick_chromium
2012/03/07 20:39:37
HANDLE handle = reinterpret_cast<HANDLE>(&buf[0]);
mazda
2012/03/08 13:14:28
Thanks. This is much simpler and cleaner.
|
+ if (FAILED(hr)) |
+ return false; |
+ |
+ // Then copy the data in the temporary render target to a temporary surface |
+ // in the system memory that is used for the final copy to |buf|. |
+ hr = device_->GetRenderTargetData(temp_render_target, temp_surface); |
+ if (FAILED(hr)) |
+ return false; |
+ |
+ const size_t buf_size = static_cast<size_t>(4 * size.GetArea()); |
+ if (buf->size() < buf_size) { |
+ buf->resize(buf_size); |
+ } |
+ |
+ D3DLOCKED_RECT locked_rect; |
apatrick_chromium
2012/03/07 20:39:37
... thereby eliminating the need for lines 318 thr
mazda
2012/03/08 13:14:28
Done.
|
+ const int kLockFlags = D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE | |
+ D3DLOCK_NOOVERWRITE; |
+ temp_surface->LockRect(&locked_rect, NULL, kLockFlags); |
apatrick_chromium
2012/03/07 20:39:37
If these lines remain, I would not assume LockRect
mazda
2012/03/08 13:14:28
I deleted this code block following your comment a
|
+ const int kBytesPerRow = 4 * size.width(); |
+ for (int y = 0; y < size.height(); ++y) { |
+ unsigned char* p1 = |
+ static_cast<unsigned char*>(locked_rect.pBits) + locked_rect.Pitch * y; |
+ unsigned char* p2 = |
+ static_cast<unsigned char*>(&(*buf)[0]) + kBytesPerRow * y; |
+ memcpy(p2, p1, kBytesPerRow); |
+ } |
+ temp_surface->UnlockRect(); |
+ |
+ return true; |
+} |
+ |
void AcceleratedPresenter::Suspend() { |
// Resize the swap chain to 1 x 1 to save memory while the presenter is not |
// in use. |
@@ -512,7 +581,11 @@ bool AcceleratedSurface::Present(HWND window) { |
return presenter_->Present(window); |
} |
+bool AcceleratedSurface::CopyTo(const gfx::Size& size, |
+ std::vector<unsigned char>* buf) { |
+ return presenter_->CopyTo(size, buf); |
+} |
+ |
void AcceleratedSurface::Suspend() { |
presenter_->Suspend(); |
} |
- |