Chromium Code Reviews| 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 4edc1ee332eb367f6d45813fd488653e42889933..005d6749d156482fe4ca55e139a9858d1fc24a65 100644 |
| --- a/ui/gfx/surface/accelerated_surface_win.cc |
| +++ b/ui/gfx/surface/accelerated_surface_win.cc |
| @@ -5,6 +5,7 @@ |
| #include "ui/gfx/surface/accelerated_surface_win.h" |
| #include <windows.h> |
| +#include <algorithm> |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| @@ -145,6 +146,82 @@ void PresentThread::ResetDevice() { |
| } |
| } |
| +bool AcceleratedPresenter::CopyTo(const gfx::Size& size, |
| + std::vector<unsigned char>* buf) { |
| + base::AutoLock locked(lock_); |
| + |
| + base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2]; |
| + HRESULT hr = swap_chain_->GetBackBuffer(0, |
|
apatrick_chromium
2012/03/08 20:15:47
swap_chain_ will be null if either no surface has
mazda
2012/03/10 07:51:37
Done.
|
| + D3DBACKBUFFER_TYPE_MONO, |
| + temp_buffer[0].Receive()); |
| + if (FAILED(hr)) |
| + return false; |
| + |
| + D3DSURFACE_DESC desc; |
| + hr = temp_buffer[0]->GetDesc(&desc); |
| + if (FAILED(hr) || (desc.Width == 0) || (desc.Height == 0)) |
| + 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. |
| + int buffer_width = desc.Width; |
| + int buffer_height = desc.Height; |
| + int read_buffer = 0; |
| + int write_buffer = 1; |
| + do { |
|
apatrick_chromium
2012/03/08 20:15:47
I believe it is possible to call GetRenderTargetDa
mazda
2012/03/10 07:51:37
Done.
|
| + buffer_width = std::max(buffer_width / 2, size.width()); |
| + buffer_height = std::max(buffer_height / 2, size.height()); |
| + temp_buffer[write_buffer].Release(); |
| + hr = present_thread_->device()->CreateRenderTarget( |
|
vangelis
2012/03/08 17:34:35
Can we avoid creating render targets for all inter
mazda
2012/03/10 07:51:37
Done.
|
| + buffer_width, |
| + buffer_height, |
| + D3DFMT_A8R8G8B8, |
| + D3DMULTISAMPLE_NONE, |
| + 0, |
| + TRUE, |
| + temp_buffer[write_buffer].Receive(), |
| + NULL); |
| + if (FAILED(hr)) |
| + return false; |
| + |
| + hr = present_thread_->device()->StretchRect(temp_buffer[read_buffer], |
| + NULL, |
| + temp_buffer[write_buffer], |
| + NULL, |
| + D3DTEXF_LINEAR); |
| + if (FAILED(hr)) |
| + return false; |
| + |
| + std::swap(read_buffer, write_buffer); |
| + } while (size != gfx::Size(buffer_width, buffer_height)); |
| + |
| + const size_t buf_size = static_cast<size_t>(4 * size.GetArea()); |
| + if (buf->size() < buf_size) { |
| + buf->resize(buf_size); |
| + } |
| + |
| + base::win::ScopedComPtr<IDirect3DSurface9> temp_surface; |
| + HANDLE handle = reinterpret_cast<HANDLE>(&(*buf)[0]); |
| + hr = present_thread_->device()->CreateOffscreenPlainSurface( |
| + size.width(), |
| + size.height(), |
| + D3DFMT_A8R8G8B8, |
| + D3DPOOL_SYSTEMMEM, |
| + temp_surface.Receive(), |
| + &handle); |
| + if (FAILED(hr)) |
| + return false; |
| + |
| + // Copy the data in the temporary buffer to the surface backed by |buf|. |
| + hr = present_thread_->device()->GetRenderTargetData( |
| + temp_buffer[read_buffer], temp_surface); |
| + if (FAILED(hr)) |
| + return false; |
| + |
| + return true; |
| +} |
| + |
| void PresentThread::Init() { |
| TRACE_EVENT0("surface", "PresentThread::Init"); |
| d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL)); |
| @@ -431,8 +508,12 @@ bool AcceleratedSurface::Present(HWND window) { |
| return false; |
| } |
| +bool AcceleratedSurface::CopyTo(const gfx::Size& size, |
| + std::vector<unsigned char>* buf) { |
| + return presenter_->CopyTo(size, buf); |
| +} |
| + |
| void AcceleratedSurface::Suspend() { |
| if (presenter_) |
| presenter_->Suspend(); |
| } |
| - |