| 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
|
| deleted file mode 100644
|
| index c6d18d9b98835aa646eac1a530b97f96fffd9330..0000000000000000000000000000000000000000
|
| --- a/ui/gfx/surface/accelerated_surface_win.cc
|
| +++ /dev/null
|
| @@ -1,683 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "ui/gfx/surface/accelerated_surface_win.h"
|
| -
|
| -#include <windows.h>
|
| -#include <algorithm>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/callback.h"
|
| -#include "base/command_line.h"
|
| -#include "base/string_number_conversions.h"
|
| -#include "base/time.h"
|
| -#include "base/debug/trace_event.h"
|
| -#include "base/file_path.h"
|
| -#include "base/lazy_instance.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/scoped_native_library.h"
|
| -#include "base/stringprintf.h"
|
| -#include "base/synchronization/waitable_event.h"
|
| -#include "base/threading/thread.h"
|
| -#include "base/threading/thread_restrictions.h"
|
| -#include "base/tracked_objects.h"
|
| -#include "base/win/wrapped_window_proc.h"
|
| -#include "ui/base/win/hwnd_util.h"
|
| -#include "ui/gfx/gl/gl_switches.h"
|
| -
|
| -namespace {
|
| -
|
| -typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version,
|
| - IDirect3D9Ex **d3d);
|
| -
|
| -const wchar_t kD3D9ModuleName[] = L"d3d9.dll";
|
| -const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex";
|
| -
|
| -UINT GetPresentationInterval() {
|
| - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
|
| - return D3DPRESENT_INTERVAL_IMMEDIATE;
|
| - else
|
| - 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
|
| -// than 2.
|
| -int GetResampleCount(const gfx::Size& source_size, const gfx::Size& dest_size) {
|
| - int width_count = 0;
|
| - int width = source_size.width();
|
| - while (width > dest_size.width()) {
|
| - ++width_count;
|
| - width >>= 1;
|
| - }
|
| - int height_count = 0;
|
| - int height = source_size.height();
|
| - while (height > dest_size.height()) {
|
| - ++height_count;
|
| - height >>= 1;
|
| - }
|
| - return std::max(width_count, height_count);
|
| -}
|
| -
|
| -// Returns half the size of |size| no smaller than |min_size|.
|
| -gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size,
|
| - const gfx::Size& min_size) {
|
| - return gfx::Size(std::max(min_size.width(), size.width() / 2),
|
| - std::max(min_size.height(), size.height() / 2));
|
| -}
|
| -
|
| -bool CreateTemporarySurface(IDirect3DDevice9* device,
|
| - const gfx::Size& size,
|
| - IDirect3DSurface9** surface) {
|
| - HRESULT hr = device->CreateRenderTarget(
|
| - size.width(),
|
| - size.height(),
|
| - D3DFMT_A8R8G8B8,
|
| - D3DMULTISAMPLE_NONE,
|
| - 0,
|
| - TRUE,
|
| - surface,
|
| - NULL);
|
| - return SUCCEEDED(hr);
|
| -}
|
| -
|
| -} // namespace anonymous
|
| -
|
| -// A PresentThread is a thread that is dedicated to presenting surfaces to a
|
| -// window. It owns a Direct3D device and a Direct3D query for this purpose.
|
| -class PresentThread : public base::Thread,
|
| - public base::RefCountedThreadSafe<PresentThread> {
|
| - public:
|
| - explicit PresentThread(const char* name);
|
| -
|
| - IDirect3DDevice9Ex* device() { return device_.get(); }
|
| - IDirect3DQuery9* query() { return query_.get(); }
|
| -
|
| - void InitDevice();
|
| - void ResetDevice();
|
| -
|
| - protected:
|
| - virtual void CleanUp();
|
| -
|
| - private:
|
| - friend class base::RefCountedThreadSafe<PresentThread>;
|
| -
|
| - ~PresentThread();
|
| -
|
| - base::ScopedNativeLibrary d3d_module_;
|
| - base::win::ScopedComPtr<IDirect3DDevice9Ex> device_;
|
| -
|
| - // This query is used to wait until a certain amount of progress has been
|
| - // made by the GPU and it is safe for the producer to modify its shared
|
| - // texture again.
|
| - base::win::ScopedComPtr<IDirect3DQuery9> query_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(PresentThread);
|
| -};
|
| -
|
| -// There is a fixed sized pool of PresentThreads and therefore the maximum
|
| -// number of Direct3D devices owned by those threads is bounded.
|
| -class PresentThreadPool {
|
| - public:
|
| - static const int kNumPresentThreads = 4;
|
| -
|
| - PresentThreadPool();
|
| - PresentThread* NextThread();
|
| -
|
| - private:
|
| - int next_thread_;
|
| - scoped_refptr<PresentThread> present_threads_[kNumPresentThreads];
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(PresentThreadPool);
|
| -};
|
| -
|
| -// A thread safe map of presenters by surface ID that returns presenters via
|
| -// a scoped_refptr to keep them alive while they are referenced.
|
| -class AcceleratedPresenterMap {
|
| - public:
|
| - AcceleratedPresenterMap();
|
| - scoped_refptr<AcceleratedPresenter> CreatePresenter(gfx::NativeWindow window);
|
| - void RemovePresenter(const scoped_refptr<AcceleratedPresenter>& presenter);
|
| - scoped_refptr<AcceleratedPresenter> GetPresenter(gfx::NativeWindow window);
|
| - private:
|
| - base::Lock lock_;
|
| - typedef std::map<gfx::NativeWindow, AcceleratedPresenter*> PresenterMap;
|
| - PresenterMap presenters_;
|
| - DISALLOW_COPY_AND_ASSIGN(AcceleratedPresenterMap);
|
| -};
|
| -
|
| -base::LazyInstance<PresentThreadPool>
|
| - g_present_thread_pool = LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -base::LazyInstance<AcceleratedPresenterMap>
|
| - g_accelerated_presenter_map = LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -PresentThread::PresentThread(const char* name) : base::Thread(name) {
|
| -}
|
| -
|
| -void PresentThread::InitDevice() {
|
| - if (device_)
|
| - return;
|
| -
|
| - TRACE_EVENT0("surface", "PresentThread::Init");
|
| - d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL));
|
| - ResetDevice();
|
| -}
|
| -
|
| -void PresentThread::ResetDevice() {
|
| - TRACE_EVENT0("surface", "PresentThread::ResetDevice");
|
| -
|
| - // This will crash some Intel drivers but we can't render anything without
|
| - // reseting the device, which would be disappointing.
|
| - query_ = NULL;
|
| - device_ = NULL;
|
| -
|
| - Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>(
|
| - d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName));
|
| - if (!create_func)
|
| - return;
|
| -
|
| - base::win::ScopedComPtr<IDirect3D9Ex> d3d;
|
| - HRESULT hr = create_func(D3D_SDK_VERSION, d3d.Receive());
|
| - if (FAILED(hr))
|
| - return;
|
| -
|
| - // Any old window will do to create the device. In practice the window to
|
| - // present to is an argument to IDirect3DDevice9::Present.
|
| - HWND window = GetShellWindow();
|
| -
|
| - D3DPRESENT_PARAMETERS parameters = { 0 };
|
| - parameters.BackBufferWidth = 1;
|
| - parameters.BackBufferHeight = 1;
|
| - parameters.BackBufferCount = 1;
|
| - parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
|
| - parameters.hDeviceWindow = window;
|
| - parameters.Windowed = TRUE;
|
| - parameters.Flags = 0;
|
| - parameters.PresentationInterval = GetPresentationInterval();
|
| - parameters.SwapEffect = D3DSWAPEFFECT_COPY;
|
| -
|
| - hr = d3d->CreateDeviceEx(
|
| - D3DADAPTER_DEFAULT,
|
| - D3DDEVTYPE_HAL,
|
| - window,
|
| - D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING |
|
| - D3DCREATE_DISABLE_PSGP_THREADING | D3DCREATE_MULTITHREADED,
|
| - ¶meters,
|
| - NULL,
|
| - device_.Receive());
|
| - if (FAILED(hr))
|
| - return;
|
| -
|
| - hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive());
|
| - if (FAILED(hr))
|
| - device_ = NULL;
|
| -}
|
| -
|
| -void PresentThread::CleanUp() {
|
| - // The D3D device and query are leaked because destroying the associated D3D
|
| - // query crashes some Intel drivers.
|
| - device_.Detach();
|
| - query_.Detach();
|
| -}
|
| -
|
| -PresentThread::~PresentThread() {
|
| - Stop();
|
| -}
|
| -
|
| -PresentThreadPool::PresentThreadPool() : next_thread_(0) {
|
| - // Do this in the constructor so present_threads_ is initialized before any
|
| - // other thread sees it. See LazyInstance documentation.
|
| - for (int i = 0; i < kNumPresentThreads; ++i) {
|
| - present_threads_[i] = new PresentThread(
|
| - base::StringPrintf("PresentThread #%d", i).c_str());
|
| - present_threads_[i]->Start();
|
| - }
|
| -}
|
| -
|
| -PresentThread* PresentThreadPool::NextThread() {
|
| - next_thread_ = (next_thread_ + 1) % kNumPresentThreads;
|
| - return present_threads_[next_thread_].get();
|
| -}
|
| -
|
| -AcceleratedPresenterMap::AcceleratedPresenterMap() {
|
| -}
|
| -
|
| -scoped_refptr<AcceleratedPresenter> AcceleratedPresenterMap::CreatePresenter(
|
| - gfx::NativeWindow window) {
|
| - scoped_refptr<AcceleratedPresenter> presenter(
|
| - new AcceleratedPresenter(window));
|
| -
|
| - base::AutoLock locked(lock_);
|
| - DCHECK(presenters_.find(window) == presenters_.end());
|
| - presenters_[window] = presenter.get();
|
| -
|
| - return presenter;
|
| -}
|
| -
|
| -void AcceleratedPresenterMap::RemovePresenter(
|
| - const scoped_refptr<AcceleratedPresenter>& presenter) {
|
| - base::AutoLock locked(lock_);
|
| - for (PresenterMap::iterator it = presenters_.begin();
|
| - it != presenters_.end();
|
| - ++it) {
|
| - if (it->second == presenter.get()) {
|
| - presenters_.erase(it);
|
| - return;
|
| - }
|
| - }
|
| -
|
| - NOTREACHED();
|
| -}
|
| -
|
| -scoped_refptr<AcceleratedPresenter> AcceleratedPresenterMap::GetPresenter(
|
| - gfx::NativeWindow window) {
|
| - base::AutoLock locked(lock_);
|
| - PresenterMap::iterator it = presenters_.find(window);
|
| - if (it == presenters_.end())
|
| - return scoped_refptr<AcceleratedPresenter>();
|
| -
|
| - return it->second;
|
| -}
|
| -
|
| -AcceleratedPresenter::AcceleratedPresenter(gfx::NativeWindow window)
|
| - : present_thread_(g_present_thread_pool.Pointer()->NextThread()),
|
| - window_(window),
|
| - event_(false, false) {
|
| -}
|
| -
|
| -scoped_refptr<AcceleratedPresenter> AcceleratedPresenter::GetForWindow(
|
| - gfx::NativeWindow window) {
|
| - return g_accelerated_presenter_map.Pointer()->GetPresenter(window);
|
| -}
|
| -
|
| -void AcceleratedPresenter::AsyncPresentAndAcknowledge(
|
| - const gfx::Size& size,
|
| - int64 surface_handle,
|
| - const base::Callback<void(bool)>& completion_task) {
|
| - if (!surface_handle) {
|
| - completion_task.Run(true);
|
| - return;
|
| - }
|
| -
|
| - present_thread_->message_loop()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge,
|
| - this,
|
| - size,
|
| - surface_handle,
|
| - completion_task));
|
| -}
|
| -
|
| -bool AcceleratedPresenter::Present() {
|
| - TRACE_EVENT0("surface", "Present");
|
| -
|
| - bool result;
|
| -
|
| - present_thread_->message_loop()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&AcceleratedPresenter::DoPresent,
|
| - this,
|
| - &result));
|
| - // http://crbug.com/125391
|
| - base::ThreadRestrictions::ScopedAllowWait allow_wait;
|
| - event_.Wait();
|
| - return result;
|
| -}
|
| -
|
| -void AcceleratedPresenter::DoPresent(bool* result)
|
| -{
|
| - *result = DoRealPresent();
|
| - event_.Signal();
|
| -}
|
| -
|
| -bool AcceleratedPresenter::DoRealPresent()
|
| -{
|
| - TRACE_EVENT0("surface", "DoRealPresent");
|
| - HRESULT hr;
|
| -
|
| - base::AutoLock locked(lock_);
|
| -
|
| - // Signal the caller to recomposite if the presenter has been suspended or no
|
| - // surface has ever been presented.
|
| - if (!swap_chain_)
|
| - return false;
|
| -
|
| - // If invalidated, do nothing. The window is gone.
|
| - if (!window_)
|
| - return true;
|
| -
|
| - RECT rect = {
|
| - 0, 0,
|
| - size_.width(), size_.height()
|
| - };
|
| -
|
| - {
|
| - TRACE_EVENT0("surface", "PresentEx");
|
| - hr = swap_chain_->Present(&rect,
|
| - &rect,
|
| - window_,
|
| - NULL,
|
| - D3DPRESENT_INTERVAL_IMMEDIATE);
|
| - if (FAILED(hr))
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool AcceleratedPresenter::CopyTo(const gfx::Size& size, void* buf) {
|
| - base::AutoLock locked(lock_);
|
| -
|
| - if (!swap_chain_)
|
| - return false;
|
| -
|
| - base::win::ScopedComPtr<IDirect3DSurface9> back_buffer;
|
| - HRESULT hr = swap_chain_->GetBackBuffer(0,
|
| - D3DBACKBUFFER_TYPE_MONO,
|
| - back_buffer.Receive());
|
| - if (FAILED(hr))
|
| - return false;
|
| -
|
| - D3DSURFACE_DESC desc;
|
| - hr = back_buffer->GetDesc(&desc);
|
| - if (FAILED(hr))
|
| - return false;
|
| -
|
| - const gfx::Size back_buffer_size(desc.Width, desc.Height);
|
| - if (back_buffer_size.IsEmpty())
|
| - return false;
|
| -
|
| - // Set up intermediate buffers needed for downsampling.
|
| - const int resample_count =
|
| - GetResampleCount(gfx::Size(desc.Width, desc.Height), 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,
|
| - final_surface.Receive()))
|
| - return false;
|
| - }
|
| - const gfx::Size half_size = GetHalfSizeNoLessThan(back_buffer_size, size);
|
| - if (resample_count > 1) {
|
| - if (!CreateTemporarySurface(present_thread_->device(),
|
| - half_size,
|
| - temp_buffer[0].Receive()))
|
| - return false;
|
| - }
|
| - if (resample_count > 2) {
|
| - const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, 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;
|
| - gfx::Size write_size = half_size;
|
| - int read_buffer_index = 1;
|
| - int write_buffer_index = 0;
|
| - for (int i = 0; i < resample_count; ++i) {
|
| - base::win::ScopedComPtr<IDirect3DSurface9> read_buffer =
|
| - (i == 0) ? back_buffer : temp_buffer[read_buffer_index];
|
| - 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()};
|
| - hr = present_thread_->device()->StretchRect(read_buffer,
|
| - &read_rect,
|
| - write_buffer,
|
| - &write_rect,
|
| - D3DTEXF_LINEAR);
|
| - if (FAILED(hr))
|
| - return false;
|
| - read_size = write_size;
|
| - write_size = GetHalfSizeNoLessThan(write_size, 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(),
|
| - 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(final_surface,
|
| - temp_surface);
|
| - if (FAILED(hr))
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void AcceleratedPresenter::Suspend() {
|
| - present_thread_->message_loop()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&AcceleratedPresenter::DoSuspend,
|
| - this));
|
| -}
|
| -
|
| -void AcceleratedPresenter::ReleaseSurface() {
|
| - present_thread_->message_loop()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&AcceleratedPresenter::DoReleaseSurface,
|
| - this));
|
| -}
|
| -
|
| -void AcceleratedPresenter::Invalidate() {
|
| - // Make any pending or future presentation tasks do nothing. Once the last
|
| - // last pending task has been ignored, the reference count on the presenter
|
| - // will go to zero and the presenter, and potentially also the present thread
|
| - // it has a reference count on, will be destroyed.
|
| - base::AutoLock locked(lock_);
|
| - window_ = NULL;
|
| -}
|
| -
|
| -AcceleratedPresenter::~AcceleratedPresenter() {
|
| -}
|
| -
|
| -static base::TimeDelta GetSwapDelay() {
|
| - CommandLine* cmd_line = CommandLine::ForCurrentProcess();
|
| - int delay = 0;
|
| - if (cmd_line->HasSwitch(switches::kGpuSwapDelay)) {
|
| - base::StringToInt(cmd_line->GetSwitchValueNative(
|
| - switches::kGpuSwapDelay).c_str(), &delay);
|
| - }
|
| - return base::TimeDelta::FromMilliseconds(delay);
|
| -}
|
| -
|
| -void AcceleratedPresenter::DoPresentAndAcknowledge(
|
| - const gfx::Size& size,
|
| - int64 surface_handle,
|
| - const base::Callback<void(bool)>& completion_task) {
|
| - TRACE_EVENT1(
|
| - "surface", "DoPresentAndAcknowledge", "surface_handle", surface_handle);
|
| -
|
| - HRESULT hr;
|
| -
|
| - base::AutoLock locked(lock_);
|
| -
|
| - // Initialize the device lazily since calling Direct3D can crash bots.
|
| - present_thread_->InitDevice();
|
| -
|
| - if (!present_thread_->device()) {
|
| - if (!completion_task.is_null())
|
| - completion_task.Run(false);
|
| - return;
|
| - }
|
| -
|
| - // Ensure the task is always run and while the lock is taken.
|
| - base::ScopedClosureRunner scoped_completion_runner(base::Bind(completion_task,
|
| - true));
|
| -
|
| - // If invalidated, do nothing, the window is gone.
|
| - if (!window_)
|
| - return;
|
| -
|
| - // Round up size so the swap chain is not continuously resized with the
|
| - // surface, which could lead to memory fragmentation.
|
| - const int kRound = 64;
|
| - gfx::Size quantized_size(
|
| - std::max(1, (size.width() + kRound - 1) / kRound * kRound),
|
| - std::max(1, (size.height() + kRound - 1) / kRound * kRound));
|
| -
|
| - // Ensure the swap chain exists and is the same size (rounded up) as the
|
| - // surface to be presented.
|
| - if (!swap_chain_ || size_ != quantized_size) {
|
| - TRACE_EVENT0("surface", "CreateAdditionalSwapChain");
|
| - size_ = quantized_size;
|
| -
|
| - D3DPRESENT_PARAMETERS parameters = { 0 };
|
| - parameters.BackBufferWidth = quantized_size.width();
|
| - parameters.BackBufferHeight = quantized_size.height();
|
| - parameters.BackBufferCount = 1;
|
| - parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
|
| - parameters.hDeviceWindow = GetShellWindow();
|
| - parameters.Windowed = TRUE;
|
| - parameters.Flags = 0;
|
| - parameters.PresentationInterval = GetPresentationInterval();
|
| - parameters.SwapEffect = D3DSWAPEFFECT_COPY;
|
| -
|
| - swap_chain_ = NULL;
|
| - HRESULT hr = present_thread_->device()->CreateAdditionalSwapChain(
|
| - ¶meters,
|
| - swap_chain_.Receive());
|
| - if (FAILED(hr))
|
| - return;
|
| - }
|
| -
|
| - if (!source_texture_.get()) {
|
| - TRACE_EVENT0("surface", "CreateTexture");
|
| - HANDLE handle = reinterpret_cast<HANDLE>(surface_handle);
|
| - hr = present_thread_->device()->CreateTexture(size.width(),
|
| - size.height(),
|
| - 1,
|
| - D3DUSAGE_RENDERTARGET,
|
| - D3DFMT_A8R8G8B8,
|
| - D3DPOOL_DEFAULT,
|
| - source_texture_.Receive(),
|
| - &handle);
|
| - if (FAILED(hr))
|
| - return;
|
| - }
|
| -
|
| - base::win::ScopedComPtr<IDirect3DSurface9> source_surface;
|
| - hr = source_texture_->GetSurfaceLevel(0, source_surface.Receive());
|
| - if (FAILED(hr))
|
| - return;
|
| -
|
| - base::win::ScopedComPtr<IDirect3DSurface9> dest_surface;
|
| - hr = swap_chain_->GetBackBuffer(0,
|
| - D3DBACKBUFFER_TYPE_MONO,
|
| - dest_surface.Receive());
|
| - if (FAILED(hr))
|
| - return;
|
| -
|
| - RECT rect = {
|
| - 0, 0,
|
| - size.width(), size.height()
|
| - };
|
| -
|
| - {
|
| - TRACE_EVENT0("surface", "StretchRect");
|
| - hr = present_thread_->device()->StretchRect(source_surface,
|
| - &rect,
|
| - dest_surface,
|
| - &rect,
|
| - D3DTEXF_NONE);
|
| - if (FAILED(hr))
|
| - return;
|
| - }
|
| -
|
| - hr = present_thread_->query()->Issue(D3DISSUE_END);
|
| - if (FAILED(hr))
|
| - return;
|
| -
|
| - // Flush so the StretchRect can be processed by the GPU while the window is
|
| - // being resized.
|
| - present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
| -
|
| - ::SetWindowPos(
|
| - window_,
|
| - NULL,
|
| - 0, 0,
|
| - size.width(), size.height(),
|
| - SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |SWP_NOOWNERZORDER |
|
| - SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING |
|
| - SWP_ASYNCWINDOWPOS | SWP_NOZORDER);
|
| -
|
| - // Wait for the StretchRect to complete before notifying the GPU process
|
| - // that it is safe to write to its backing store again.
|
| - {
|
| - TRACE_EVENT0("surface", "spin");
|
| - do {
|
| - hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
| -
|
| - if (hr == S_FALSE)
|
| - Sleep(1);
|
| - } while (hr == S_FALSE);
|
| - }
|
| -
|
| - static const base::TimeDelta swap_delay = GetSwapDelay();
|
| - if (swap_delay.ToInternalValue())
|
| - base::PlatformThread::Sleep(swap_delay);
|
| -
|
| - {
|
| - TRACE_EVENT0("surface", "Present");
|
| - hr = swap_chain_->Present(&rect, &rect, window_, NULL, 0);
|
| - if (FAILED(hr) &&
|
| - FAILED(present_thread_->device()->CheckDeviceState(window_))) {
|
| - present_thread_->ResetDevice();
|
| - }
|
| - }
|
| -}
|
| -
|
| -void AcceleratedPresenter::DoSuspend() {
|
| - base::AutoLock locked(lock_);
|
| - swap_chain_ = NULL;
|
| -}
|
| -
|
| -void AcceleratedPresenter::DoReleaseSurface() {
|
| - base::AutoLock locked(lock_);
|
| - source_texture_.Release();
|
| -}
|
| -
|
| -AcceleratedSurface::AcceleratedSurface(gfx::NativeWindow window)
|
| - : presenter_(g_accelerated_presenter_map.Pointer()->CreatePresenter(
|
| - window)) {
|
| -}
|
| -
|
| -AcceleratedSurface::~AcceleratedSurface() {
|
| - g_accelerated_presenter_map.Pointer()->RemovePresenter(presenter_);
|
| - presenter_->Invalidate();
|
| -}
|
| -
|
| -bool AcceleratedSurface::Present() {
|
| - return presenter_->Present();
|
| -}
|
| -
|
| -bool AcceleratedSurface::CopyTo(const gfx::Size& size, void* buf) {
|
| - return presenter_->CopyTo(size, buf);
|
| -}
|
| -
|
| -void AcceleratedSurface::Suspend() {
|
| - presenter_->Suspend();
|
| -}
|
|
|