diff options
author | jbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-27 22:07:42 +0000 |
---|---|---|
committer | jbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-27 22:07:42 +0000 |
commit | 33ed5f8e92e48ad85f9a81f6c6c7b1d8c56ffb02 (patch) | |
tree | 6f7fd8f24d5303af1ab685c8c5f94572ef2b9c8e /ui | |
parent | 6408d04ab220bae8bd373d839bcee1399e22a50d (diff) | |
download | chromium_src-33ed5f8e92e48ad85f9a81f6c6c7b1d8c56ffb02.zip chromium_src-33ed5f8e92e48ad85f9a81f6c6c7b1d8c56ffb02.tar.gz chromium_src-33ed5f8e92e48ad85f9a81f6c6c7b1d8c56ffb02.tar.bz2 |
Remove Windows accelerated surface support.
Presentation now only happens directly from the GPU process, so this code isn't used anymore.
BUG=325947
Review URL: https://codereview.chromium.org/140173004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247312 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/surface/accelerated_surface_transformer_win.cc | 736 | ||||
-rw-r--r-- | ui/surface/accelerated_surface_transformer_win.h | 228 | ||||
-rw-r--r-- | ui/surface/accelerated_surface_transformer_win.hlsl | 300 | ||||
-rw-r--r-- | ui/surface/accelerated_surface_transformer_win_unittest.cc | 895 | ||||
-rw-r--r-- | ui/surface/accelerated_surface_win.cc | 1106 | ||||
-rw-r--r-- | ui/surface/accelerated_surface_win.h | 223 | ||||
-rw-r--r-- | ui/surface/compile_hlsl.py | 161 | ||||
-rw-r--r-- | ui/surface/d3d9_utils_win.cc | 168 | ||||
-rw-r--r-- | ui/surface/d3d9_utils_win.h | 87 | ||||
-rw-r--r-- | ui/surface/surface.gyp | 69 | ||||
-rw-r--r-- | ui/surface/surface_switches.cc | 19 | ||||
-rw-r--r-- | ui/surface/surface_switches.h | 19 |
12 files changed, 0 insertions, 4011 deletions
diff --git a/ui/surface/accelerated_surface_transformer_win.cc b/ui/surface/accelerated_surface_transformer_win.cc deleted file mode 100644 index 0706a1a..0000000 --- a/ui/surface/accelerated_surface_transformer_win.cc +++ /dev/null @@ -1,736 +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/surface/accelerated_surface_transformer_win.h" - -#include <vector> - -#include "accelerated_surface_transformer_win_hlsl_compiled.h" -#include "base/debug/trace_event.h" -#include "base/memory/ref_counted.h" -#include "base/metrics/histogram.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/win/scoped_comptr.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/size.h" -#include "ui/surface/d3d9_utils_win.h" -#include "ui/surface/surface_export.h" - -using base::win::ScopedComPtr; -using std::vector; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertRGBtoY8UV44; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertUV44toU2V2; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsOneTexture; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsFetch2Pixels; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsFetch4Pixels; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsOneTexture; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsFetch4PixelsScale2; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertRGBtoY; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertRGBtoU; -using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertRGBtoV; - -namespace d3d_utils = ui_surface_d3d9_utils; - -namespace { - -struct Vertex { - float x, y, z, w; - float u, v; -}; - -const static D3DVERTEXELEMENT9 g_vertexElements[] = { - { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0 }, - { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 }, - D3DDECL_END() -}; - -class ScopedRenderTargetRestorer { - public: - ScopedRenderTargetRestorer(IDirect3DDevice9* device, - int render_target_id) - : device_(device), - target_id_(render_target_id) { - device_->GetRenderTarget(target_id_, original_render_target_.Receive()); - } - ~ScopedRenderTargetRestorer() { - device_->SetRenderTarget(target_id_, original_render_target_); - } - private: - ScopedComPtr<IDirect3DDevice9> device_; - int target_id_; - ScopedComPtr<IDirect3DSurface9> original_render_target_; -}; - -// 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::Rect& src_subrect, - const gfx::Size& dst_size) { - // At least one copy is required, since the back buffer itself is not - // lockable. - int min_resample_count = 1; - int width_count = 0; - int width = src_subrect.width(); - while (width > dst_size.width()) { - ++width_count; - width >>= 1; - } - int height_count = 0; - int height = src_subrect.height(); - while (height > dst_size.height()) { - ++height_count; - height >>= 1; - } - return std::max(std::max(width_count, height_count), - min_resample_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)); -} - -} // namespace - -AcceleratedSurfaceTransformer::AcceleratedSurfaceTransformer() - : device_supports_multiple_render_targets_(false), - vertex_shader_sources_(), - pixel_shader_sources_() { - - // Associate passes with actual shader programs. - vertex_shader_sources_[ONE_TEXTURE] = kVsOneTexture; - pixel_shader_sources_[ONE_TEXTURE] = kPsOneTexture; - - vertex_shader_sources_[RGB_TO_YV12_FAST__PASS_1_OF_2] = kVsFetch4Pixels; - pixel_shader_sources_[RGB_TO_YV12_FAST__PASS_1_OF_2] = kPsConvertRGBtoY8UV44; - - vertex_shader_sources_[RGB_TO_YV12_FAST__PASS_2_OF_2] = kVsFetch2Pixels; - pixel_shader_sources_[RGB_TO_YV12_FAST__PASS_2_OF_2] = kPsConvertUV44toU2V2; - - vertex_shader_sources_[RGB_TO_YV12_SLOW__PASS_1_OF_3] = kVsFetch4Pixels; - pixel_shader_sources_[RGB_TO_YV12_SLOW__PASS_1_OF_3] = kPsConvertRGBtoY; - - vertex_shader_sources_[RGB_TO_YV12_SLOW__PASS_2_OF_3] = kVsFetch4PixelsScale2; - pixel_shader_sources_[RGB_TO_YV12_SLOW__PASS_2_OF_3] = kPsConvertRGBtoU; - - vertex_shader_sources_[RGB_TO_YV12_SLOW__PASS_3_OF_3] = kVsFetch4PixelsScale2; - pixel_shader_sources_[RGB_TO_YV12_SLOW__PASS_3_OF_3] = kPsConvertRGBtoV; - - COMPILE_ASSERT(NUM_SHADERS == 6, must_initialize_shader_sources); -} - -bool AcceleratedSurfaceTransformer::Init(IDirect3DDevice9* device) { - bool result = DoInit(device); - if (!result) { - ReleaseAll(); - } - return result; -} - -bool AcceleratedSurfaceTransformer::DoInit(IDirect3DDevice9* device) { - device_ = device; - - { - D3DCAPS9 caps; - HRESULT hr = device->GetDeviceCaps(&caps); - if (FAILED(hr)) - return false; - - device_supports_multiple_render_targets_ = (caps.NumSimultaneousRTs >= 2); - - // Log statistics about which paths we take. - UMA_HISTOGRAM_BOOLEAN("GPU.AcceleratedSurfaceTransformerCanUseMRT", - device_supports_multiple_render_targets()); - } - - // Force compilation of all shaders that could be used on this GPU. - if (!CompileShaderCombo(ONE_TEXTURE)) - return false; - - if (device_supports_multiple_render_targets()) { - if (!CompileShaderCombo(RGB_TO_YV12_FAST__PASS_1_OF_2) || - !CompileShaderCombo(RGB_TO_YV12_FAST__PASS_2_OF_2)) { - return false; - } - } else { - if (!CompileShaderCombo(RGB_TO_YV12_SLOW__PASS_1_OF_3) || - !CompileShaderCombo(RGB_TO_YV12_SLOW__PASS_2_OF_3) || - !CompileShaderCombo(RGB_TO_YV12_SLOW__PASS_3_OF_3)) { - return false; - } - } - COMPILE_ASSERT(NUM_SHADERS == 6, must_compile_at_doinit); - - ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration; - HRESULT hr = device_->CreateVertexDeclaration(g_vertexElements, - vertex_declaration.Receive()); - if (FAILED(hr)) - return false; - hr = device_->SetVertexDeclaration(vertex_declaration); - if (FAILED(hr)) - return false; - - return true; -} - -bool AcceleratedSurfaceTransformer::CompileShaderCombo( - ShaderCombo shader) { - if (!vertex_shaders_[shader]) { - HRESULT hr = device_->CreateVertexShader( - reinterpret_cast<const DWORD*>(vertex_shader_sources_[shader]), - vertex_shaders_[shader].Receive()); - - if (FAILED(hr)) - return false; - - for (int i = 0; i < NUM_SHADERS; ++i) { - if (vertex_shader_sources_[i] == vertex_shader_sources_[shader] && - i != shader) { - vertex_shaders_[i] = vertex_shaders_[shader]; - } - } - } - - if (!pixel_shaders_[shader]) { - HRESULT hr = device_->CreatePixelShader( - reinterpret_cast<const DWORD*>(pixel_shader_sources_[shader]), - pixel_shaders_[shader].Receive()); - - if (FAILED(hr)) - return false; - - for (int i = 0; i < NUM_SHADERS; ++i) { - if (pixel_shader_sources_[i] == pixel_shader_sources_[shader] && - i != shader) { - pixel_shaders_[i] = pixel_shaders_[shader]; - } - } - } - - return true; -} - -void AcceleratedSurfaceTransformer::ReleaseAll() { - for (int i = 0; i < NUM_SHADERS; i++) { - vertex_shaders_[i] = NULL; - pixel_shaders_[i] = NULL; - } - - user_scratch_texture_ = NULL; - uv_scratch_texture_ = NULL; - y_scratch_surface_ = NULL; - u_scratch_surface_ = NULL; - v_scratch_surface_ = NULL; - for (int i = 0; i < arraysize(scaler_scratch_surfaces_); i++) - scaler_scratch_surfaces_[i] = NULL; - - device_ = NULL; -} -void AcceleratedSurfaceTransformer::DetachAll() { - for (int i = 0; i < NUM_SHADERS; i++) { - vertex_shaders_[i].Detach(); - pixel_shaders_[i].Detach(); - } - - user_scratch_texture_.Detach(); - uv_scratch_texture_.Detach(); - y_scratch_surface_.Detach(); - u_scratch_surface_.Detach(); - v_scratch_surface_.Detach(); - for (int i = 0; i < arraysize(scaler_scratch_surfaces_); i++) - scaler_scratch_surfaces_[i].Detach(); - - device_.Detach(); -} - -bool AcceleratedSurfaceTransformer::CopyInverted( - IDirect3DTexture9* src_texture, - IDirect3DSurface9* dst_surface, - const gfx::Size& dst_size) { - return CopyWithTextureScale(src_texture, dst_surface, dst_size, 1.0f, -1.0f); -} - -bool AcceleratedSurfaceTransformer::Copy( - IDirect3DTexture9* src_texture, - IDirect3DSurface9* dst_surface, - const gfx::Size& dst_size) { - return CopyWithTextureScale(src_texture, dst_surface, dst_size, 1.0f, 1.0f); -} - -bool AcceleratedSurfaceTransformer::CopyWithTextureScale( - IDirect3DTexture9* src_texture, - IDirect3DSurface9* dst_surface, - const gfx::Size& dst_size, - float texture_scale_x, - float texture_scale_y) { - - if (!SetShaderCombo(ONE_TEXTURE)) - return false; - - // Set the kTextureScale vertex shader constant, which is assigned to - // register 1. - float texture_scale[4] = {texture_scale_x, texture_scale_y, 0, 0}; - device()->SetVertexShaderConstantF(1, texture_scale, 1); - - ScopedRenderTargetRestorer render_target_restorer(device(), 0); - device()->SetRenderTarget(0, dst_surface); - device()->SetTexture(0, src_texture); - - D3DVIEWPORT9 viewport = { - 0, 0, - dst_size.width(), dst_size.height(), - 0, 1 - }; - device()->SetViewport(&viewport); - - if (d3d_utils::GetSize(src_texture) == dst_size) { - device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - } else { - device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - } - device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - - DrawScreenAlignedQuad(dst_size); - - // Clear surface references. - device()->SetTexture(0, NULL); - return true; -} - -void AcceleratedSurfaceTransformer::DrawScreenAlignedQuad( - const gfx::Size& size) { - const float target_size[4] = { size.width(), size.height(), 0, 0}; - - // Set the uniform shader constant |kRenderTargetSize|, which is bound - // to register c0. - device()->SetVertexShaderConstantF(0, target_size, 1); - - // We always send down the same vertices. The vertex program will take - // care of doing resolution-dependent position adjustment. - Vertex vertices[] = { - { -1, +1, 0.5f, 1, 0, 0 }, - { +1, +1, 0.5f, 1, 1, 0 }, - { +1, -1, 0.5f, 1, 1, 1 }, - { -1, -1, 0.5f, 1, 0, 1 } - }; - - device()->BeginScene(); - device()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, - 2, - vertices, - sizeof(vertices[0])); - device()->EndScene(); - -} - -bool AcceleratedSurfaceTransformer::GetIntermediateTexture( - const gfx::Size& size, - IDirect3DTexture9** texture, - IDirect3DSurface9** texture_level_zero) { - if (!d3d_utils::CreateOrReuseRenderTargetTexture(device(), - size, - &user_scratch_texture_, - texture_level_zero)) - return false; - - *texture = ScopedComPtr<IDirect3DTexture9>(user_scratch_texture_).Detach(); - return true; -} - -// Resize an RGB surface using repeated linear interpolation. -bool AcceleratedSurfaceTransformer::ResizeBilinear( - IDirect3DSurface9* src_surface, - const gfx::Rect& src_subrect, - IDirect3DSurface9* dst_surface, - const gfx::Rect& dst_rect) { - COMPILE_ASSERT(arraysize(scaler_scratch_surfaces_) == 2, surface_count); - - gfx::Size src_size = src_subrect.size(); - gfx::Size dst_size = dst_rect.size(); - - if (src_size.IsEmpty() || dst_size.IsEmpty()) - return false; - - HRESULT hr = S_OK; - // Set up intermediate buffers needed for downsampling. - const int resample_count = GetResampleCount(src_subrect, dst_size); - const gfx::Size half_size = - GetHalfSizeNoLessThan(src_subrect.size(), dst_size); - if (resample_count > 1) { - if (!d3d_utils::CreateOrReuseLockableSurface(device(), - half_size, - &scaler_scratch_surfaces_[0])) - return false; - } - if (resample_count > 2) { - const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, dst_size); - if (!d3d_utils::CreateOrReuseLockableSurface(device(), - quarter_size, - &scaler_scratch_surfaces_[1])) - return false; - } - - // Repeat downsampling the surface until its size becomes identical to - // |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; - for (int i = 0; i < resample_count; ++i) { - TRACE_EVENT0("gpu", "StretchRect"); - IDirect3DSurface9* read_buffer = - (i == 0) ? src_surface : scaler_scratch_surfaces_[read_buffer_index]; - IDirect3DSurface9* write_buffer; - RECT write_rect; - if (i == resample_count - 1) { - write_buffer = dst_surface; - write_rect = dst_rect.ToRECT(); - } else { - write_buffer = scaler_scratch_surfaces_[write_buffer_index]; - write_rect = gfx::Rect(write_size).ToRECT(); - } - - hr = device()->StretchRect(read_buffer, - &read_rect, - write_buffer, - &write_rect, - D3DTEXF_LINEAR); - - if (FAILED(hr)) - return false; - read_rect = write_rect; - write_size = GetHalfSizeNoLessThan(write_size, dst_size); - std::swap(read_buffer_index, write_buffer_index); - } - - return true; -} - -bool AcceleratedSurfaceTransformer::TransformRGBToYV12( - IDirect3DTexture9* src_surface, - const gfx::Size& dst_size, - IDirect3DSurface9** dst_y, - IDirect3DSurface9** dst_u, - IDirect3DSurface9** dst_v) { - gfx::Size packed_y_size; - gfx::Size packed_uv_size; - if (!AllocYUVBuffers(dst_size, &packed_y_size, &packed_uv_size, - dst_y, dst_u, dst_v)) { - return false; - } - - if (device_supports_multiple_render_targets()) { - return TransformRGBToYV12_MRT(src_surface, - dst_size, - packed_y_size, - packed_uv_size, - *dst_y, - *dst_u, - *dst_v); - } else { - return TransformRGBToYV12_WithoutMRT(src_surface, - dst_size, - packed_y_size, - packed_uv_size, - *dst_y, - *dst_u, - *dst_v); - } -} - -bool AcceleratedSurfaceTransformer::ReadFast(IDirect3DSurface9* gpu_surface, - uint8* dst, - int dst_bytes_per_row, - int dst_num_rows, - int dst_stride) { - // TODO(nick): Compared to GetRenderTargetData, LockRect+memcpy is 50% faster - // on some systems, but 100x slower on others. We should have logic here to - // choose the best path, probably by adaptively trying both and picking the - // faster one. http://crbug.com/168532 - return ReadByGetRenderTargetData(gpu_surface, dst, dst_bytes_per_row, - dst_num_rows, dst_stride); -} - -bool AcceleratedSurfaceTransformer::ReadByLockAndCopy( - IDirect3DSurface9* gpu_surface, - uint8* dst, - int dst_bytes_per_row, - int dst_num_rows, - int dst_stride) { - D3DLOCKED_RECT locked_rect; - { - TRACE_EVENT0("gpu", "LockRect"); - HRESULT hr = gpu_surface->LockRect(&locked_rect, NULL, - D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to lock surface"; - return false; - } - } - - { - TRACE_EVENT0("gpu", "memcpy"); - uint8* dst_row = dst; - uint8* src_row = reinterpret_cast<uint8*>(locked_rect.pBits); - for (int i = 0; i < dst_num_rows; i++) { - memcpy(dst_row, src_row, dst_bytes_per_row); - src_row += locked_rect.Pitch; - dst_row += dst_stride; - } - } - gpu_surface->UnlockRect(); - return true; -} - -bool AcceleratedSurfaceTransformer::ReadByGetRenderTargetData( - IDirect3DSurface9* gpu_surface, - uint8* dst, - int dst_bytes_per_row, - int dst_num_rows, - int dst_stride) { - HRESULT hr = 0; - ScopedComPtr<IDirect3DSurface9> system_surface; - gfx::Size src_size = d3d_utils::GetSize(gpu_surface); - - // Depending on pitch and alignment, we might be able to wrap |dst| in an - // offscreen- plain surface for a direct copy. - const bool direct_copy = (dst_stride == dst_bytes_per_row && - src_size.width() * 4 == dst_bytes_per_row && - dst_num_rows >= src_size.height()); - - { - TRACE_EVENT0("gpu", "CreateOffscreenPlainSurface"); - HANDLE handle = reinterpret_cast<HANDLE>(dst); - hr = device()->CreateOffscreenPlainSurface(src_size.width(), - src_size.height(), - D3DFMT_A8R8G8B8, - D3DPOOL_SYSTEMMEM, - system_surface.Receive(), - direct_copy ? &handle : NULL); - if (!SUCCEEDED(hr)) { - LOG(ERROR) << "Failed to create offscreen plain surface."; - return false; - } - } - - { - TRACE_EVENT0("gpu", "GetRenderTargetData"); - hr = device()->GetRenderTargetData(gpu_surface, system_surface); - if (FAILED(hr)) { - LOG(ERROR) << "Failed GetRenderTargetData"; - return false; - } - } - - if (direct_copy) { - // We're done: |system_surface| is a wrapper around |dst|. - return true; - } else { - // Extra memcpy required from |system_surface| to |dst|. - return ReadByLockAndCopy(system_surface, dst, dst_bytes_per_row, - dst_num_rows, dst_stride); - } -} - -bool AcceleratedSurfaceTransformer::AllocYUVBuffers( - const gfx::Size& dst_size, - gfx::Size* y_size, - gfx::Size* uv_size, - IDirect3DSurface9** dst_y, - IDirect3DSurface9** dst_u, - IDirect3DSurface9** dst_v) { - - // Y is full height, packed into 4 components. - *y_size = gfx::Size((dst_size.width() + 3) / 4, dst_size.height()); - - // U and V are half the size (rounded up) of Y. - *uv_size = gfx::Size((y_size->width() + 1) / 2, (y_size->height() + 1) / 2); - - if (!d3d_utils::CreateOrReuseLockableSurface(device(), *y_size, - &y_scratch_surface_)) { - return false; - } - if (!d3d_utils::CreateOrReuseLockableSurface(device(), *uv_size, - &u_scratch_surface_)) { - return false; - } - if (!d3d_utils::CreateOrReuseLockableSurface(device(), *uv_size, - &v_scratch_surface_)) { - return false; - } - - *dst_y = ScopedComPtr<IDirect3DSurface9>(y_scratch_surface_).Detach(); - *dst_u = ScopedComPtr<IDirect3DSurface9>(u_scratch_surface_).Detach(); - *dst_v = ScopedComPtr<IDirect3DSurface9>(v_scratch_surface_).Detach(); - - return true; -} - -bool AcceleratedSurfaceTransformer::TransformRGBToYV12_MRT( - IDirect3DTexture9* src_surface, - const gfx::Size& dst_size, - const gfx::Size& packed_y_size, - const gfx::Size& packed_uv_size, - IDirect3DSurface9* dst_y, - IDirect3DSurface9* dst_u, - IDirect3DSurface9* dst_v) { - TRACE_EVENT0("gpu", "RGBToYV12_MRT"); - - ScopedRenderTargetRestorer color0_restorer(device(), 0); - ScopedRenderTargetRestorer color1_restorer(device(), 1); - - // Create an intermediate surface to hold the UUVV values. This is color - // target 1 for the first pass, and texture 0 for the second pass. Its - // values are not read afterwards. - - ScopedComPtr<IDirect3DSurface9> uv_as_surface; - if (!d3d_utils::CreateOrReuseRenderTargetTexture(device(), - packed_y_size, - &uv_scratch_texture_, - uv_as_surface.Receive())) { - return false; - } - - // Clamping is required if (dst_size.width() % 8 != 0) or if - // (dst_size.height != 0), so we set it always. Both passes rely on this. - device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - - ///////////////////////////////////////// - // Pass 1: RGB --(scaled)--> YYYY + UUVV - SetShaderCombo(RGB_TO_YV12_FAST__PASS_1_OF_2); - - // Enable bilinear filtering if scaling is required. The filtering will take - // place entirely in the first pass. - if (d3d_utils::GetSize(src_surface) != dst_size) { - device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - } else { - device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - } - - device()->SetTexture(0, src_surface); - device()->SetRenderTarget(0, dst_y); - device()->SetRenderTarget(1, uv_as_surface); - DrawScreenAlignedQuad(dst_size); - - ///////////////////////////////////////// - // Pass 2: UUVV -> UUUU + VVVV - SetShaderCombo(RGB_TO_YV12_FAST__PASS_2_OF_2); - - // The second pass uses bilinear minification to achieve vertical scaling, - // so enable it always. - device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - - device()->SetTexture(0, uv_scratch_texture_); - device()->SetRenderTarget(0, dst_u); - device()->SetRenderTarget(1, dst_v); - DrawScreenAlignedQuad(packed_y_size); - - // Clear surface references. - device()->SetTexture(0, NULL); - return true; -} - -bool AcceleratedSurfaceTransformer::TransformRGBToYV12_WithoutMRT( - IDirect3DTexture9* src_surface, - const gfx::Size& dst_size, - const gfx::Size& packed_y_size, - const gfx::Size& packed_uv_size, - IDirect3DSurface9* dst_y, - IDirect3DSurface9* dst_u, - IDirect3DSurface9* dst_v) { - TRACE_EVENT0("gpu", "RGBToYV12_WithoutMRT"); - - ScopedRenderTargetRestorer color0_restorer(device(), 0); - - ScopedComPtr<IDirect3DTexture9> scaled_src_surface; - - // If scaling is requested, do it to a temporary texture. The MRT path - // gets a scale for free, so we need to support it here too (even though - // it's an extra operation). - if (d3d_utils::GetSize(src_surface) == dst_size) { - scaled_src_surface = src_surface; - } else { - ScopedComPtr<IDirect3DSurface9> dst_level0; - if (!d3d_utils::CreateOrReuseRenderTargetTexture( - device(), dst_size, &uv_scratch_texture_, dst_level0.Receive())) { - return false; - } - if (!Copy(src_surface, dst_level0, dst_size)) { - return false; - } - scaled_src_surface = uv_scratch_texture_; - } - - // Input texture is the same for all three passes. - device()->SetTexture(0, scaled_src_surface); - - // Clamping is required if (dst_size.width() % 8 != 0) or if - // (dst_size.height != 0), so we set it always. All passes rely on this. - device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - - ///////////////////// - // Pass 1: RGB -> Y. - SetShaderCombo(RGB_TO_YV12_SLOW__PASS_1_OF_3); - - // Pass 1 just needs point sampling. - device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - - device()->SetRenderTarget(0, dst_y); - DrawScreenAlignedQuad(dst_size); - - // Passes 2 and 3 rely on bilinear minification to downsample U and V. - device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - - ///////////////////// - // Pass 2: RGB -> U. - SetShaderCombo(RGB_TO_YV12_SLOW__PASS_2_OF_3); - device()->SetRenderTarget(0, dst_u); - DrawScreenAlignedQuad(dst_size); - - ///////////////////// - // Pass 3: RGB -> V. - SetShaderCombo(RGB_TO_YV12_SLOW__PASS_3_OF_3); - device()->SetRenderTarget(0, dst_v); - DrawScreenAlignedQuad(dst_size); - - // Clear surface references. - device()->SetTexture(0, NULL); - return true; -} - -IDirect3DDevice9* AcceleratedSurfaceTransformer::device() { - return device_; -} - -bool AcceleratedSurfaceTransformer::SetShaderCombo(ShaderCombo combo) { - // Compile shaders on first use, if needed. Normally the compilation should - // already have happened at Init() time, but test code might force - // us down an unusual path. - if (!CompileShaderCombo(combo)) - return false; - - HRESULT hr = device()->SetVertexShader(vertex_shaders_[combo]); - if (!SUCCEEDED(hr)) - return false; - hr = device()->SetPixelShader(pixel_shaders_[combo]); - if (!SUCCEEDED(hr)) - return false; - return true; -} diff --git a/ui/surface/accelerated_surface_transformer_win.h b/ui/surface/accelerated_surface_transformer_win.h deleted file mode 100644 index b04d0ab..0000000 --- a/ui/surface/accelerated_surface_transformer_win.h +++ /dev/null @@ -1,228 +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. - -#ifndef UI_SURFACE_ACCELERATED_SURFACE_TRANSFORMER_WIN_H_ -#define UI_SURFACE_ACCELERATED_SURFACE_TRANSFORMER_WIN_H_ - -#include <d3d9.h> - -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/win/scoped_comptr.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/size.h" -#include "ui/surface/surface_export.h" - -namespace gfx { -class Size; -class Rect; -} // namespace gfx - -// Provides useful image filtering operations that are implemented -// efficiently on DirectX9-class hardware using fragment programs. -class SURFACE_EXPORT AcceleratedSurfaceTransformer { - public: - // Constructs an uninitialized surface transformer. Call Init() before - // using the resulting object. - AcceleratedSurfaceTransformer(); - - // Init() initializes the transformer to operate on a device. This must be - // called before any other method of this class, and it must be called - // again after ReleaseAll() or DetachAll() before the class is used. - // - // Returns true if successful. - bool Init(IDirect3DDevice9* device); - - // ReleaseAll() releases all direct3d resource references. - void ReleaseAll(); - - // DetachAll() leaks all direct3d resource references. This exists in order to - // work around particular driver bugs, and should only be called at shutdown. - // TODO(ncarter): Update the leak expectations before checkin. - void DetachAll(); - - // Draw a textured quad to a surface, flipping orientation in the y direction. - bool CopyInverted( - IDirect3DTexture9* src_texture, - IDirect3DSurface9* dst_surface, - const gfx::Size& dst_size); - - // Draw a textured quad to a surface. - bool Copy( - IDirect3DTexture9* src_texture, - IDirect3DSurface9* dst_surface, - const gfx::Size& dst_size); - - // Get an intermediate buffer of a particular |size|, that can be used as the - // output of one transformation and the to another. The returned surface - // belongs to an internal cache, and is invalidated by a subsequent call to - // this method. - bool GetIntermediateTexture( - const gfx::Size& size, - IDirect3DTexture9** texture, - IDirect3DSurface9** texture_level_zero); - - // Resize a surface using repeated bilinear interpolation. - bool ResizeBilinear( - IDirect3DSurface9* src_surface, - const gfx::Rect& src_subrect, - IDirect3DSurface9* dst_surface, - const gfx::Rect& dst_subrect); - - // Color format conversion from RGB to planar YV12 (also known as YUV420). - // - // YV12 is effectively a twelve bit per pixel format consisting of a full- - // size y (luminance) plane and half-width, half-height u and v (blue and - // red chrominance) planes. This method will allocate three lockable surfaces, - // one for each plane, and return them via the arguments |dst_y|, |dst_u|, - // and |dst_v|. These surface will be created with an ARGB D3DFORMAT, but - // should be interpreted as the appropriate single-byte format when locking. - // - // The dimensions of the outputs (when interpreted as single-component data) - // are as follows: - // |dst_y| : width and height exactly |dst_size| - // |dst_u| : width and height are each half of |dst_size|, rounded up. - // |dst_v| : width and height are each half of |dst_size|, rounded up. - // - // If |src_texture|'s dimensions do not match |dst_size|, the source will be - // bilinearly interpolated during conversion. - // - // Returns true if successful. Caller must be certain to release the surfaces - // even if this function returns false. The returned surfaces belong to an - // internal cache, and are invalidated by a subsequent call to this method. - bool TransformRGBToYV12( - IDirect3DTexture9* src_texture, - const gfx::Size& dst_size, - IDirect3DSurface9** dst_y, - IDirect3DSurface9** dst_u, - IDirect3DSurface9** dst_v); - - // Synchronously copy from a D3D surface into a caller-allocated buffer. This - // will dispatch to one of a couple techniques, depending on which is - // determined to be the faster method for the current device. - bool ReadFast(IDirect3DSurface9* gpu_surface, - uint8* dst, - int dst_bytes_per_row, - int dst_num_rows, - int dst_stride); - - // Do a read using a particular technique. Which of these is faster depends on - // the hardware. Intended for testing; production code ought to call - // ReadFast(). - bool ReadByLockAndCopy(IDirect3DSurface9* gpu_surface, - uint8* dst, - int dst_bytes_per_row, - int dst_num_rows, - int dst_stride); - bool ReadByGetRenderTargetData(IDirect3DSurface9* gpu_surface, - uint8* dst, - int dst_bytes_per_row, - int dst_num_rows, - int dst_stride); - - private: - friend class AcceleratedSurfaceTransformerTest; - FRIEND_TEST_ALL_PREFIXES(AcceleratedSurfaceTransformerTest, Init); - - enum ShaderCombo { - ONE_TEXTURE, - RGB_TO_YV12_FAST__PASS_1_OF_2, - RGB_TO_YV12_FAST__PASS_2_OF_2, - RGB_TO_YV12_SLOW__PASS_1_OF_3, - RGB_TO_YV12_SLOW__PASS_2_OF_3, - RGB_TO_YV12_SLOW__PASS_3_OF_3, - NUM_SHADERS - }; - - // Efficient RGB->YV12 in two passes, but requires a device capable of writing - // multiple render targets at the same time. - // - // Returns true if successful. - bool TransformRGBToYV12_MRT( - IDirect3DTexture9* src_surface, - const gfx::Size& dst_size, - const gfx::Size& packed_y_size, - const gfx::Size& packed_uv_size, - IDirect3DSurface9* dst_y, - IDirect3DSurface9* dst_u, - IDirect3DSurface9* dst_v); - - // Slower, less efficient RGB->YV12; does not require the device to have - // multiple render target capability. Runs at about half speed of the fast - // path. - // - // Returns true if successful. - bool TransformRGBToYV12_WithoutMRT( - IDirect3DTexture9* src_surface, - const gfx::Size& dst_size, - const gfx::Size& packed_y_size, - const gfx::Size& packed_uv_size, - IDirect3DSurface9* dst_y, - IDirect3DSurface9* dst_u, - IDirect3DSurface9* dst_v); - - // Helper to allocate appropriately size YUV buffers, accounting for various - // roundings. The sizes of the buffers (in terms of ARGB pixels) are returned - // as |packed_y_size| and |packed_uv_size|. - // - // Returns true if successful. Caller must be certain to release the surfaces - // even if this function returns false. The returned belong to an internal - // cache. - bool AllocYUVBuffers( - const gfx::Size& dst_size, - gfx::Size* packed_y_size, - gfx::Size* packed_uv_size, - IDirect3DSurface9** dst_y, - IDirect3DSurface9** dst_u, - IDirect3DSurface9** dst_v); - - bool CopyWithTextureScale( - IDirect3DTexture9* src_texture, - IDirect3DSurface9* dst_surface, - const gfx::Size& dst_size, - float texture_scale_x, - float texture_scale_y); - - // Set the active vertex and pixel shader combination. - // - // Returns true if successful. - bool SetShaderCombo(ShaderCombo combo); - - // Compiles a vertex and pixel shader combination, if not already compiled. - // - // Returns true if successful. - bool CompileShaderCombo(ShaderCombo shader_combo_name); - - bool DoInit(IDirect3DDevice9* device); - - void DrawScreenAlignedQuad(const gfx::Size& dst_size); - - bool device_supports_multiple_render_targets() const { - return device_supports_multiple_render_targets_; - } - - IDirect3DDevice9* device(); - - base::win::ScopedComPtr<IDirect3DDevice9> device_; - base::win::ScopedComPtr<IDirect3DVertexShader9> vertex_shaders_[NUM_SHADERS]; - base::win::ScopedComPtr<IDirect3DPixelShader9> pixel_shaders_[NUM_SHADERS]; - - // Temporary and scratch surfaces; cached to avoid frequent reallocation. - base::win::ScopedComPtr<IDirect3DTexture9> user_scratch_texture_; - base::win::ScopedComPtr<IDirect3DTexture9> uv_scratch_texture_; - base::win::ScopedComPtr<IDirect3DSurface9> y_scratch_surface_; - base::win::ScopedComPtr<IDirect3DSurface9> u_scratch_surface_; - base::win::ScopedComPtr<IDirect3DSurface9> v_scratch_surface_; - base::win::ScopedComPtr<IDirect3DSurface9> scaler_scratch_surfaces_[2]; - - bool device_supports_multiple_render_targets_; - const BYTE* vertex_shader_sources_[NUM_SHADERS]; - const BYTE* pixel_shader_sources_[NUM_SHADERS]; - DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceTransformer); -}; - -#endif // UI_SURFACE_ACCELERATED_SURFACE_TRANSFORMER_WIN_H_ diff --git a/ui/surface/accelerated_surface_transformer_win.hlsl b/ui/surface/accelerated_surface_transformer_win.hlsl deleted file mode 100644 index aa105ce..0000000 --- a/ui/surface/accelerated_surface_transformer_win.hlsl +++ /dev/null @@ -1,300 +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. - -// @gyp_namespace(ui_surface) -// Compiles into C++ as 'accelerated_surface_transformer_win_hlsl_compiled.h' - -struct Vertex { - float4 position : POSITION; - float2 texCoord : TEXCOORD0; -}; - -texture t; -sampler s; - -extern uniform float2 kRenderTargetSize : c0; -extern uniform float2 kTextureScale : c1; - -// @gyp_compile(vs_2_0, vsOneTexture) -// -// Passes a position and texture coordinate to the pixel shader. -Vertex vsOneTexture(Vertex input) { - // Texture scale is typically just 1 (to do nothing) or -1 (to flip). - input.texCoord = ((2 * (input.texCoord - 0.5) * kTextureScale) + 1) / 2; - input.position.x += -1 / kRenderTargetSize.x; - input.position.y += 1 / kRenderTargetSize.y; - return input; -}; - -// @gyp_compile(ps_2_0, psOneTexture) -// -// Samples a texture at the given texture coordinate and returns the result. -float4 psOneTexture(float2 texCoord : TEXCOORD0) : COLOR0 { - return tex2D(s, texCoord); -}; - -// Return |value| rounded up to the nearest multiple of |multiple|. -float alignTo(float value, float multiple) { - // |multiple| is usually a compile-time constant; this check allows - // the compiler to avoid the fmod when possible. - if (multiple == 1) - return value; - - // Biasing the value provides numeric stability. We expect |value| to - // be an integer; this prevents 4.001 from being rounded up to 8. - float biased_value = value - 0.5; - return biased_value + multiple - fmod(biased_value, multiple); -} - -float4 packForByteOrder(float4 value) { - return value.bgra; -} - -// Adjust the input vertex to address the correct range of texels. This depends -// on the value of the shader constant |kRenderTargetSize|, as well as an -// alignment factor |align| that effectively specifies the footprint of the -// texel samples done by this shader pass, and is used to correct when that -// footprint size doesn't align perfectly with the actual input size. -Vertex adjustForAlignmentAndPacking(Vertex vtx, float2 align) { - float src_width = kRenderTargetSize.x; - float src_height = kRenderTargetSize.y; - - // Because our caller expects to be sampling |align.x| many pixels from src at - // a time, if src's width isn't evenly divisible by |align.x|, it is necessary - // to pretend that the source is slightly bigger than it is. - float bloated_src_width = alignTo(src_width, align.x); - float bloated_src_height = alignTo(src_height, align.y); - - // When bloated_src_width != src_width, we'll adjust the texture coordinates - // to sample past the edge of the vtx; clamping will produce extra copies of - // the last row. - float texture_x_scale = bloated_src_width / src_width; - float texture_y_scale = bloated_src_height / src_height; - - // Adjust positions so that we're addressing full fragments in the output, per - // the top-left filling convention. The shifts would be equivalent to - // 1/dst_width and 1/dst_height, if we were to calculate those explicitly. - vtx.position.x -= align.x / bloated_src_width; - vtx.position.y += align.y / bloated_src_height; - - // Apply the texture scale - vtx.texCoord.x *= texture_x_scale; - vtx.texCoord.y *= texture_y_scale; - - return vtx; -} - -/////////////////////////////////////////////////////////////////////// -// RGB24 to YV12 in two passes; writing two 8888 targets each pass. -// -// YV12 is full-resolution luma and half-resolution blue/red chroma. -// -// (original) -// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB -// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB -// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB -// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB -// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB -// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB -// | -// | (y plane) (temporary) -// | YYYY YYYY UVUV UVUV -// +--> { YYYY YYYY + UVUV UVUV } -// YYYY YYYY UVUV UVUV -// First YYYY YYYY UVUV UVUV -// pass YYYY YYYY UVUV UVUV -// YYYY YYYY UVUV UVUV -// | -// | (u plane) (v plane) -// Second | UUUU VVVV -// pass +--> { UUUU + VVVV } -// UUUU VVVV -// -/////////////////////////////////////////////////////////////////////// - -// Phase one of RGB24->YV12 conversion: vsFetch4Pixels/psConvertRGBtoY8UV44 -// -// @gyp_compile(vs_2_0, vsFetch4Pixels) -// @gyp_compile(ps_2_0, psConvertRGBtoY8UV44) -// -// Writes four source pixels at a time to a full-size Y plane and a half-width -// interleaved UV plane. After execution, the Y plane is complete but the UV -// planes still need to be de-interleaved and vertically scaled. -// -void vsFetch4Pixels(in Vertex vertex, - out float4 position : POSITION, - out float2 texCoord0 : TEXCOORD0, - out float2 texCoord1 : TEXCOORD1, - out float2 texCoord2 : TEXCOORD2, - out float2 texCoord3 : TEXCOORD3) { - Vertex adjusted = adjustForAlignmentAndPacking(vertex, float2(4, 1)); - - // Set up four taps, aligned to texel centers if the src's true size is - // |kRenderTargetSize|, and doing bilinear interpolation otherwise. - float2 one_texel_x = float2(1 / kRenderTargetSize.x, 0); - position = adjusted.position; - texCoord0 = adjusted.texCoord - 1.5f * one_texel_x; - texCoord1 = adjusted.texCoord - 0.5f * one_texel_x; - texCoord2 = adjusted.texCoord + 0.5f * one_texel_x; - texCoord3 = adjusted.texCoord + 1.5f * one_texel_x; -}; - -struct YV16QuadPixel -{ - float4 YYYY : COLOR0; - float4 UUVV : COLOR1; -}; - -// Color conversion constants. -static const float3x1 rgb_to_y = float3x1( +0.257f, +0.504f, +0.098f ); -static const float3x1 rgb_to_u = float3x1( -0.148f, -0.291f, +0.439f ); -static const float3x1 rgb_to_v = float3x1( +0.439f, -0.368f, -0.071f ); -static const float y_bias = 0.0625f; -static const float uv_bias = 0.5f; - -YV16QuadPixel psConvertRGBtoY8UV44(float2 texCoord0 : TEXCOORD0, - float2 texCoord1 : TEXCOORD1, - float2 texCoord2 : TEXCOORD2, - float2 texCoord3 : TEXCOORD3) { - // Load the four texture samples into a matrix. - float4x3 rgb_quad_pixel = float4x3(tex2D(s, texCoord0).rgb, - tex2D(s, texCoord1).rgb, - tex2D(s, texCoord2).rgb, - tex2D(s, texCoord3).rgb); - - // RGB -> Y conversion (x4). - float4 yyyy = mul(rgb_quad_pixel, rgb_to_y) + y_bias; - - // Average adjacent texture samples while converting RGB->UV. This is the same - // as color converting then averaging, but slightly less math. These values - // will be in the range [-0.439f, +0.439f] and still need to have the bias - // term applied. - float2x3 rgb_double_pixel = float2x3(rgb_quad_pixel[0] + rgb_quad_pixel[1], - rgb_quad_pixel[2] + rgb_quad_pixel[3]); - float2 uu = mul(rgb_double_pixel, rgb_to_u / 2); - float2 vv = mul(rgb_double_pixel, rgb_to_v / 2); - - // Package the result to account for BGRA byte ordering. - YV16QuadPixel result; - result.YYYY = packForByteOrder(yyyy); - result.UUVV.xyzw = float4(uu, vv) + uv_bias; // Apply uv bias. - return result; -}; - -// Phase two of RGB24->YV12 conversion: vsFetch2Pixels/psConvertUV44toU2V2 -// -// @gyp_compile(vs_2_0, vsFetch2Pixels) -// @gyp_compile(ps_2_0, psConvertUV44toU2V2) -// -// Deals with UV only. Input is interleaved UV pixels, already scaled -// horizontally, packed two per RGBA texel. Output is two color planes U and V, -// packed four to a RGBA pixel. -// -// Vertical scaling happens via a half-texel offset and bilinear interpolation -// during texture sampling. -void vsFetch2Pixels(in Vertex vertex, - out float4 position : POSITION, - out float2 texCoord0 : TEXCOORD0, - out float2 texCoord1 : TEXCOORD1) { - // We fetch two texels in the horizontal direction, and scale by 2 in the - // vertical direction. - Vertex adjusted = adjustForAlignmentAndPacking(vertex, float2(2, 2)); - - // Setup the two texture coordinates. No need to adjust texCoord.y; it's - // already at the mid-way point between the two rows. Horizontally, we'll - // fetch two texels so that we have enough data to fill our output. - float2 one_texel_x = float2(1 / kRenderTargetSize.x, 0); - position = adjusted.position; - texCoord0 = adjusted.texCoord - 0.5f * one_texel_x; - texCoord1 = adjusted.texCoord + 0.5f * one_texel_x; -}; - -struct UV8QuadPixel { - float4 UUUU : COLOR0; - float4 VVVV : COLOR1; -}; - -UV8QuadPixel psConvertUV44toU2V2(float2 texCoord0 : TEXCOORD0, - float2 texCoord1 : TEXCOORD1) { - // We're just sampling two pixels and unswizzling them. There's no need to do - // vertical scaling with math, since bilinear interpolation in the sampler - // takes care of that. - float4 lo_uuvv = tex2D(s, texCoord0); - float4 hi_uuvv = tex2D(s, texCoord1); - UV8QuadPixel result; - result.UUUU = packForByteOrder(float4(lo_uuvv.xy, hi_uuvv.xy)); - result.VVVV = packForByteOrder(float4(lo_uuvv.zw, hi_uuvv.zw)); - return result; -}; - - -/////////////////////////////////////////////////////////////////////// -// RGB24 to YV12 in three passes, without MRT: one pass per output color plane. -// vsFetch4Pixels is the common vertex shader for all three passes. -// -// Note that this technique will not do full bilinear filtering on its RGB -// input (you'd get correctly filtered Y, but aliasing in U and V). -// -// Pass 1: vsFetch4Pixels + psConvertRGBToY -// Pass 2: vsFetch4Pixels_Scale2 + psConvertRGBToU -// Pass 3: vsFetch4Pixels_Scale2 + psConvertRGBToV -// -// @gyp_compile(vs_2_0, vsFetch4Pixels_Scale2) -// @gyp_compile(ps_2_0, psConvertRGBtoY) -// @gyp_compile(ps_2_0, psConvertRGBtoU) -// @gyp_compile(ps_2_0, psConvertRGBtoV) -// -/////////////////////////////////////////////////////////////////////// -void vsFetch4Pixels_Scale2(in Vertex vertex, - out float4 position : POSITION, - out float2 texCoord0 : TEXCOORD0, - out float2 texCoord1 : TEXCOORD1, - out float2 texCoord2 : TEXCOORD2, - out float2 texCoord3 : TEXCOORD3) { - Vertex adjusted = adjustForAlignmentAndPacking(vertex, float2(8, 2)); - - // Set up four taps, each of which samples a 2x2 texel quad at the midpoint. - float2 one_texel_x = float2(1 / kRenderTargetSize.x, 0); - position = adjusted.position; - texCoord0 = adjusted.texCoord - 3 * one_texel_x; - texCoord1 = adjusted.texCoord - 1 * one_texel_x; - texCoord2 = adjusted.texCoord + 1 * one_texel_x; - texCoord3 = adjusted.texCoord + 3 * one_texel_x; -}; - -// RGB -> Y, four samples at a time. -float4 psConvertRGBtoY(float2 texCoord0 : TEXCOORD0, - float2 texCoord1 : TEXCOORD1, - float2 texCoord2 : TEXCOORD2, - float2 texCoord3 : TEXCOORD3) : COLOR0 { - float4x3 rgb_quad_pixel = float4x3(tex2D(s, texCoord0).rgb, - tex2D(s, texCoord1).rgb, - tex2D(s, texCoord2).rgb, - tex2D(s, texCoord3).rgb); - return packForByteOrder(mul(rgb_quad_pixel, rgb_to_y) + y_bias); -} - -// RGB -> U, four samples at a time. -float4 psConvertRGBtoU(float2 texCoord0 : TEXCOORD0, - float2 texCoord1 : TEXCOORD1, - float2 texCoord2 : TEXCOORD2, - float2 texCoord3 : TEXCOORD3) : COLOR0 { - float4x3 rgb_quad_pixel = float4x3(tex2D(s, texCoord0).rgb, - tex2D(s, texCoord1).rgb, - tex2D(s, texCoord2).rgb, - tex2D(s, texCoord3).rgb); - return packForByteOrder(mul(rgb_quad_pixel, rgb_to_u) + uv_bias); -} - -// RGB -> V, four samples at a time. -float4 psConvertRGBtoV(float2 texCoord0 : TEXCOORD0, - float2 texCoord1 : TEXCOORD1, - float2 texCoord2 : TEXCOORD2, - float2 texCoord3 : TEXCOORD3) : COLOR0 { - float4x3 rgb_quad_pixel = float4x3(tex2D(s, texCoord0).rgb, - tex2D(s, texCoord1).rgb, - tex2D(s, texCoord2).rgb, - tex2D(s, texCoord3).rgb); - return packForByteOrder(mul(rgb_quad_pixel, rgb_to_v) + uv_bias); -} diff --git a/ui/surface/accelerated_surface_transformer_win_unittest.cc b/ui/surface/accelerated_surface_transformer_win_unittest.cc deleted file mode 100644 index 968720f..0000000 --- a/ui/surface/accelerated_surface_transformer_win_unittest.cc +++ /dev/null @@ -1,895 +0,0 @@ -// Copyright (c) 2013 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 <d3d9.h> -#include <random> - -#include "base/basictypes.h" -#include "base/file_util.h" -#include "base/hash.h" -#include "base/scoped_native_library.h" -#include "base/strings/stringprintf.h" -#include "base/time/time.h" -#include "base/win/scoped_comptr.h" -#include "base/win/windows_version.h" -#include "media/base/simd/convert_rgb_to_yuv.h" -#include "media/base/yuv_convert.h" -#include "skia/ext/image_operations.h" -#include "testing/gtest/include/gtest/gtest-param-test.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/codec/png_codec.h" -#include "ui/gfx/rect.h" -#include "ui/surface/accelerated_surface_transformer_win.h" -#include "ui/surface/accelerated_surface_win.h" -#include "ui/surface/d3d9_utils_win.h" - -namespace d3d_utils = ui_surface_d3d9_utils; - -using base::win::ScopedComPtr; -using std::uniform_int_distribution; - -namespace { - -// Debug flag, useful when hacking on tests. -const bool kDumpImagesOnFailure = false; - -SkBitmap ToSkBitmap(IDirect3DSurface9* surface, bool is_single_channel) { - D3DLOCKED_RECT locked_rect; - EXPECT_HRESULT_SUCCEEDED( - surface->LockRect(&locked_rect, NULL, D3DLOCK_READONLY)); - - SkBitmap result; - gfx::Size size = d3d_utils::GetSize(surface); - if (is_single_channel) - size = gfx::Size(size.width() * 4, size.height()); - result.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height(), - 0, kOpaque_SkAlphaType); - result.allocPixels(); - result.lockPixels(); - for (int y = 0; y < size.height(); ++y) { - uint8* row8 = reinterpret_cast<uint8*>(locked_rect.pBits) + - (y * locked_rect.Pitch); - if (is_single_channel) { - for (int x = 0; x < size.width(); ++x) { - *result.getAddr32(x, y) = SkColorSetRGB(row8[x], row8[x], row8[x]); - } - } else { - uint32* row32 = reinterpret_cast<uint32*>(row8); - for (int x = 0; x < size.width(); ++x) { - *result.getAddr32(x, y) = row32[x] | 0xFF000000; - } - } - } - result.unlockPixels(); - result.setImmutable(); - surface->UnlockRect(); - return result; -} - -bool WritePNGFile(const SkBitmap& bitmap, const base::FilePath& file_path) { - std::vector<unsigned char> png_data; - const bool discard_transparency = true; - if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, - discard_transparency, - &png_data) && - base::CreateDirectory(file_path.DirName())) { - char* data = reinterpret_cast<char*>(&png_data[0]); - int size = static_cast<int>(png_data.size()); - return file_util::WriteFile(file_path, data, size) == size; - } - return false; -} - -} // namespace - -// Test fixture for AcceleratedSurfaceTransformer. -// -// This class is parameterized so that it runs only on Vista+. See -// WindowsVersionIfVistaOrBetter() for details on this works. -class AcceleratedSurfaceTransformerTest : public testing::TestWithParam<int> { - public: - AcceleratedSurfaceTransformerTest() : color_error_tolerance_(0) {}; - - IDirect3DDevice9Ex* device() { return device_.get(); } - - virtual void SetUp() { - if (!d3d_module_.is_valid()) { - if (!d3d_utils::LoadD3D9(&d3d_module_)) { - GTEST_FAIL() << "Could not load d3d9.dll"; - return; - } - } - if (!d3d_utils::CreateDevice(d3d_module_, - D3DDEVTYPE_HAL, - D3DPRESENT_INTERVAL_IMMEDIATE, - device_.Receive())) { - GTEST_FAIL() << "Could not create Direct3D device."; - return; - } - - SeedRandom("default"); - } - - virtual void TearDown() { - device_ = NULL; - } - - // Gets a human-readable identifier of the graphics hardware being used, - // intended for use inside of SCOPED_TRACE(). - std::string GetAdapterInfo() { - ScopedComPtr<IDirect3D9> d3d; - EXPECT_HRESULT_SUCCEEDED(device()->GetDirect3D(d3d.Receive())); - D3DADAPTER_IDENTIFIER9 info; - EXPECT_HRESULT_SUCCEEDED(d3d->GetAdapterIdentifier(0, 0, &info)); - return base::StringPrintf( - "Running on graphics hardware: %s", info.Description); - } - - void SeedRandom(const char* seed) { - rng_.seed(base::Hash(seed)); - random_dword_.reset(); - } - - // Driver workaround: on an Intel GPU (Mobile Intel 965 Express), it seems - // necessary to flush between drawing and locking, for the synchronization - // to behave properly. - void BeforeLockWorkaround() { - EXPECT_HRESULT_SUCCEEDED( - device()->Present(0, 0, 0, 0)); - } - - void WarnOnMissingFeatures(AcceleratedSurfaceTransformer* gpu_ops) { - // Prints a single warning line if some tests are feature-dependent - // and the feature is not supported by the current GPU. - if (!gpu_ops->device_supports_multiple_render_targets()) { - LOG(WARNING) << "MRT not supported, some tests will be skipped. " - << GetAdapterInfo(); - } - } - - // Locks and fills a surface with a checkerboard pattern where the colors - // are random but the total image pattern is horizontally and vertically - // symmetric. - void FillSymmetricRandomCheckerboard( - IDirect3DSurface9* lockable_surface, - const gfx::Size& size, - int checker_square_size) { - - D3DLOCKED_RECT locked_rect; - ASSERT_HRESULT_SUCCEEDED( - lockable_surface->LockRect(&locked_rect, NULL, D3DLOCK_DISCARD)); - DWORD* surface = reinterpret_cast<DWORD*>(locked_rect.pBits); - ASSERT_EQ(0, locked_rect.Pitch % sizeof(DWORD)); - int pitch = locked_rect.Pitch / sizeof(DWORD); - - for (int y = 0; y < (size.height() + 1) / 2; y += checker_square_size) { - for (int x = 0; x < (size.width() + 1) / 2; x += checker_square_size) { - DWORD color = RandomColor(); - int y_limit = std::min(size.height() / 2, y + checker_square_size - 1); - int x_limit = std::min(size.width() / 2, x + checker_square_size - 1); - for (int y_lo = y; y_lo <= y_limit; y_lo++) { - for (int x_lo = x; x_lo <= x_limit; x_lo++) { - int y_hi = size.height() - 1 - y_lo; - int x_hi = size.width() - 1 - x_lo; - surface[x_lo + y_lo*pitch] = color; - surface[x_lo + y_hi*pitch] = color; - surface[x_hi + y_lo*pitch] = color; - surface[x_hi + y_hi*pitch] = color; - } - } - } - } - - lockable_surface->UnlockRect(); - } - - void FillRandomCheckerboard( - IDirect3DSurface9* lockable_surface, - const gfx::Size& size, - int checker_square_size) { - - D3DLOCKED_RECT locked_rect; - ASSERT_HRESULT_SUCCEEDED( - lockable_surface->LockRect(&locked_rect, NULL, D3DLOCK_DISCARD)); - DWORD* surface = reinterpret_cast<DWORD*>(locked_rect.pBits); - ASSERT_EQ(0, locked_rect.Pitch % sizeof(DWORD)); - int pitch = locked_rect.Pitch / sizeof(DWORD); - - for (int y = 0; y <= size.height(); y += checker_square_size) { - for (int x = 0; x <= size.width(); x += checker_square_size) { - DWORD color = RandomColor(); - int y_limit = std::min(size.height(), y + checker_square_size); - int x_limit = std::min(size.width(), x + checker_square_size); - for (int square_y = y; square_y < y_limit; square_y++) { - for (int square_x = x; square_x < x_limit; square_x++) { - surface[square_x + square_y*pitch] = color; - } - } - } - } - - lockable_surface->UnlockRect(); - } - - // Approximate color-equality check. Allows for some rounding error. - bool AssertSameColor(DWORD color_a, DWORD color_b) { - if (color_a == color_b) - return true; - uint8* a = reinterpret_cast<uint8*>(&color_a); - uint8* b = reinterpret_cast<uint8*>(&color_b); - int max_error = 0; - for (int i = 0; i < 4; i++) - max_error = std::max(max_error, - std::abs(static_cast<int>(a[i]) - b[i])); - - if (max_error <= color_error_tolerance()) - return true; - - std::string expected_color = - base::StringPrintf("%3d, %3d, %3d, %3d", a[0], a[1], a[2], a[3]); - std::string actual_color = - base::StringPrintf("%3d, %3d, %3d, %3d", b[0], b[1], b[2], b[3]); - EXPECT_EQ(expected_color, actual_color) - << "Componentwise color difference was " - << max_error << "; max allowed is " << color_error_tolerance(); - - return false; - } - -bool AssertSameColor(uint8 color_a, uint8 color_b) { - if (color_a == color_b) - return true; - int max_error = std::abs((int) color_a - (int) color_b); - if (max_error <= color_error_tolerance()) - return true; - ADD_FAILURE() << "Colors not equal: " - << base::StringPrintf("0x%x", color_a) - << " vs. " << base::StringPrintf("0x%x", color_b); - return false; - } - - // Asserts that an image is symmetric with respect to itself: both - // horizontally and vertically, within the tolerance of AssertSameColor. - void AssertSymmetry(IDirect3DSurface9* lockable_surface, - const gfx::Size& size) { - BeforeLockWorkaround(); - - D3DLOCKED_RECT locked_rect; - ASSERT_HRESULT_SUCCEEDED( - lockable_surface->LockRect(&locked_rect, NULL, D3DLOCK_READONLY)); - ASSERT_EQ(0, locked_rect.Pitch % sizeof(DWORD)); - int pitch = locked_rect.Pitch / sizeof(DWORD); - DWORD* surface = reinterpret_cast<DWORD*>(locked_rect.pBits); - for (int y_lo = 0; y_lo < size.height() / 2; y_lo++) { - int y_hi = size.height() - 1 - y_lo; - for (int x_lo = 0; x_lo < size.width() / 2; x_lo++) { - int x_hi = size.width() - 1 - x_lo; - if (!AssertSameColor(surface[x_lo + y_lo*pitch], - surface[x_hi + y_lo*pitch])) { - lockable_surface->UnlockRect(); - GTEST_FAIL() << "Pixels (" << x_lo << ", " << y_lo << ") vs. " - << "(" << x_hi << ", " << y_lo << ")"; - } - if (!AssertSameColor(surface[x_hi + y_lo*pitch], - surface[x_hi + y_hi*pitch])) { - lockable_surface->UnlockRect(); - GTEST_FAIL() << "Pixels (" << x_hi << ", " << y_lo << ") vs. " - << "(" << x_hi << ", " << y_hi << ")"; - } - if (!AssertSameColor(surface[x_hi + y_hi*pitch], - surface[x_lo + y_hi*pitch])) { - lockable_surface->UnlockRect(); - GTEST_FAIL() << "Pixels (" << x_hi << ", " << y_hi << ") vs. " - << "(" << x_lo << ", " << y_hi << ")"; - } - } - } - lockable_surface->UnlockRect(); - } - - // Asserts that the actual image is a bit-identical, vertically mirrored - // copy of the expected image. - void AssertIsInvertedCopy(const gfx::Size& size, - IDirect3DSurface9* expected, - IDirect3DSurface9* actual) { - BeforeLockWorkaround(); - - D3DLOCKED_RECT locked_expected, locked_actual; - ASSERT_HRESULT_SUCCEEDED( - expected->LockRect(&locked_expected, NULL, D3DLOCK_READONLY)); - ASSERT_HRESULT_SUCCEEDED( - actual->LockRect(&locked_actual, NULL, D3DLOCK_READONLY)); - ASSERT_EQ(0, locked_expected.Pitch % sizeof(DWORD)); - int pitch = locked_expected.Pitch / sizeof(DWORD); - DWORD* expected_image = reinterpret_cast<DWORD*>(locked_expected.pBits); - DWORD* actual_image = reinterpret_cast<DWORD*>(locked_actual.pBits); - for (int y = 0; y < size.height(); y++) { - int y_actual = size.height() - 1 - y; - for (int x = 0; x < size.width(); ++x) - if (!AssertSameColor(expected_image[y*pitch + x], - actual_image[y_actual*pitch + x])) { - expected->UnlockRect(); - actual->UnlockRect(); - GTEST_FAIL() << "Pixels (" << x << ", " << y << ") vs. " - << "(" << x << ", " << y_actual << ")"; - } - } - expected->UnlockRect(); - actual->UnlockRect(); - } - - protected: - DWORD RandomColor() { - return random_dword_(rng_); - } - - void set_color_error_tolerance(int value) { - color_error_tolerance_ = value; - } - - int color_error_tolerance() { - return color_error_tolerance_; - } - - void DoResizeBilinearTest(AcceleratedSurfaceTransformer* gpu_ops, - const gfx::Size& src_size, - const gfx::Size& dst_size, - int checkerboard_size) { - - SCOPED_TRACE( - base::StringPrintf( - "Resizing %dx%d -> %dx%d at checkerboard size of %d", - src_size.width(), src_size.height(), - dst_size.width(), dst_size.height(), - checkerboard_size)); - - set_color_error_tolerance(4); - - base::win::ScopedComPtr<IDirect3DSurface9> src, dst; - ASSERT_TRUE(d3d_utils::CreateOrReuseLockableSurface( - device(), src_size, &src)) - << "Could not create src render target"; - ASSERT_TRUE(d3d_utils::CreateOrReuseLockableSurface( - device(), dst_size, &dst)) - << "Could not create dst render target"; - - FillSymmetricRandomCheckerboard(src, src_size, checkerboard_size); - - ASSERT_TRUE(gpu_ops->ResizeBilinear(src, gfx::Rect(src_size), dst, - gfx::Rect(dst_size))); - - AssertSymmetry(dst, dst_size); - } - - void CreateRandomCheckerboardTexture( - const gfx::Size& size, - int checkerboard_size, - base::win::ScopedComPtr<IDirect3DSurface9>* reference_surface, - base::win::ScopedComPtr<IDirect3DTexture9>* result) { - base::win::ScopedComPtr<IDirect3DSurface9> dst; - ASSERT_TRUE(d3d_utils::CreateOrReuseLockableSurface(device(), size, - reference_surface)); - ASSERT_TRUE(d3d_utils::CreateOrReuseRenderTargetTexture(device(), size, - result, dst.Receive())); - FillRandomCheckerboard(*reference_surface, size, checkerboard_size); - ASSERT_HRESULT_SUCCEEDED( - device()->StretchRect( - *reference_surface, NULL, dst, NULL, D3DTEXF_NONE)); - } - - void AssertSame(int width_in_bytes, int height, uint8* reference, - IDirect3DSurface9* lockable) { - BeforeLockWorkaround(); - - D3DLOCKED_RECT locked_rect; - ASSERT_HRESULT_SUCCEEDED( - lockable->LockRect(&locked_rect, NULL, D3DLOCK_READONLY)); - uint8* actual = reinterpret_cast<uint8*>(locked_rect.pBits); - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width_in_bytes; ++x) { - if (!AssertSameColor(reference[y * width_in_bytes + x], - actual[y * locked_rect.Pitch + x])) { - lockable->UnlockRect(); - GTEST_FAIL() << "At pixel (" << x << ", " << y << ")"; - } - } - } - lockable->UnlockRect(); - } - - void DoCopyInvertedTest(AcceleratedSurfaceTransformer* gpu_ops, - const gfx::Size& size) { - - SCOPED_TRACE(base::StringPrintf( - "CopyInverted @ %dx%d", size.width(), size.height())); - - set_color_error_tolerance(0); - - base::win::ScopedComPtr<IDirect3DSurface9> dst, reference_pattern; - base::win::ScopedComPtr<IDirect3DTexture9> src; - - CreateRandomCheckerboardTexture(size, 1, &reference_pattern, &src); - - // Alloc a slightly larger image 75% of the time, to test that the - // viewport is set properly. - const int kAlign = 4; - gfx::Size alloc_size((size.width() + kAlign - 1) / kAlign * kAlign, - (size.height() + kAlign - 1) / kAlign * kAlign); - - ASSERT_TRUE(d3d_utils::CreateOrReuseLockableSurface(device(), alloc_size, - &dst)) << "Could not create dst render target."; - - ASSERT_TRUE(gpu_ops->CopyInverted(src, dst, size)); - AssertIsInvertedCopy(size, reference_pattern, dst); - } - - - void DoYUVConversionTest(AcceleratedSurfaceTransformer* gpu_ops, - const gfx::Size& src_size, - int checkerboard_size) { - // Test the non-MRT implementation, and the MRT implementation as well - // (if supported by the device). - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(gpu_ops, src_size, src_size, - checkerboard_size, false)); - if (gpu_ops->device_supports_multiple_render_targets()) { - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(gpu_ops, src_size, src_size, - checkerboard_size, true)); - } - } - - void DoYUVConversionScaleTest(AcceleratedSurfaceTransformer* gpu_ops, - const gfx::Size& src_size, - const gfx::Size& dst_size) { - // Test the non-MRT implementation, and the MRT implementation as well - // (if supported by the device). - if (gpu_ops->device_supports_multiple_render_targets()) { - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(gpu_ops, src_size, dst_size, 4, true)); - } - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(gpu_ops, src_size, dst_size, 4, false)); - } - - void DoYUVConversionTest(AcceleratedSurfaceTransformer* gpu_ops, - const gfx::Size& src_size, - const gfx::Size& dst_size, - int checkerboard_size, - boolean use_multi_render_targets) { - SCOPED_TRACE( - base::StringPrintf( - "YUV Converting %dx%d at checkerboard size of %d; MRT %s", - src_size.width(), src_size.height(), - checkerboard_size, - use_multi_render_targets ? "enabled" : "disabled")); - - - base::win::ScopedComPtr<IDirect3DTexture9> src; - base::win::ScopedComPtr<IDirect3DSurface9> reference; - base::win::ScopedComPtr<IDirect3DSurface9> dst_y, dst_u, dst_v; - - // TODO(ncarter): Use a better error metric that measures aggregate error - // rather than simply max error. There seems to be slightly more error at - // higher resolutions, maybe due to precision issues during rasterization - // (or maybe more pixels = more test trials). Results are usually to an - // error of 1, but we must use a tolerance of 3. - set_color_error_tolerance(3); - CreateRandomCheckerboardTexture(src_size, checkerboard_size, &reference, - &src); - - gfx::Size packed_y_size, packed_uv_size; - - ASSERT_TRUE(gpu_ops->AllocYUVBuffers(dst_size, - &packed_y_size, - &packed_uv_size, - dst_y.Receive(), - dst_u.Receive(), - dst_v.Receive())); - - // Actually do the conversion. - if (use_multi_render_targets) { - ASSERT_TRUE(gpu_ops->TransformRGBToYV12_MRT(src, - dst_size, - packed_y_size, - packed_uv_size, - dst_y, - dst_u, - dst_v)); - } else { - ASSERT_TRUE(gpu_ops->TransformRGBToYV12_WithoutMRT(src, - dst_size, - packed_y_size, - packed_uv_size, - dst_y, - dst_u, - dst_v)); - } - - // UV size (in bytes/samples) is half, rounded up. - gfx::Size uv_size((dst_size.width() + 1) / 2, - (dst_size.height() + 1) / 2); - - // Generate a reference bitmap by calling a software implementation. - SkBitmap reference_rgb = ToSkBitmap(reference, false); - SkBitmap reference_rgb_scaled; - if (dst_size == src_size) { - reference_rgb_scaled = reference_rgb; - } else { - // We'll call Copy to do the bilinear scaling if needed. - base::win::ScopedComPtr<IDirect3DSurface9> reference_scaled; - ASSERT_TRUE( - d3d_utils::CreateOrReuseLockableSurface( - device(), dst_size, &reference_scaled)); - ASSERT_TRUE(gpu_ops->Copy(src, reference_scaled, dst_size)); - BeforeLockWorkaround(); - reference_rgb_scaled = ToSkBitmap(reference_scaled, false); - } - - scoped_ptr<uint8[]> reference_y(new uint8[dst_size.GetArea()]); - scoped_ptr<uint8[]> reference_u(new uint8[uv_size.GetArea()]); - scoped_ptr<uint8[]> reference_v(new uint8[uv_size.GetArea()]); - reference_rgb_scaled.lockPixels(); - media::ConvertRGB32ToYUV_SSE2_Reference( - reinterpret_cast<uint8*>(reference_rgb_scaled.getAddr32(0, 0)), - &reference_y[0], - &reference_u[0], - &reference_v[0], - dst_size.width(), - dst_size.height(), - reference_rgb_scaled.rowBytes(), - dst_size.width(), - uv_size.width()); - reference_rgb_scaled.unlockPixels(); - - // Check for equality of the reference and the actual. - AssertSame(dst_size.width(), dst_size.height(), &reference_y[0], dst_y); - AssertSame(uv_size.width(), uv_size.height(), &reference_u[0], dst_u); - AssertSame(uv_size.width(), uv_size.height(), &reference_v[0], dst_v); - - if (kDumpImagesOnFailure && HasFatalFailure()) { - // Note that this will dump the full u and v buffers, including - // extra columns added due to packing. That means up to 7 extra - // columns for uv, and up to 3 extra columns for y. - WritePNGFile(reference_rgb, - base::FilePath(FILE_PATH_LITERAL("test_fail_src.png"))); - WritePNGFile(reference_rgb_scaled, - base::FilePath( - FILE_PATH_LITERAL("test_fail_src_scaled.png"))); - WritePNGFile(ToSkBitmap(dst_y, true), - base::FilePath(FILE_PATH_LITERAL("test_fail_y.png"))); - WritePNGFile(ToSkBitmap(dst_u, true), - base::FilePath(FILE_PATH_LITERAL("test_fail_u.png"))); - WritePNGFile(ToSkBitmap(dst_v, true), - base::FilePath(FILE_PATH_LITERAL("test_fail_v.png"))); - } - } - - int color_error_tolerance_; - uniform_int_distribution<DWORD> random_dword_; - std::mt19937 rng_; - base::ScopedNativeLibrary d3d_module_; - base::win::ScopedComPtr<IDirect3DDevice9Ex> device_; -}; - -// Fails on some bots because Direct3D isn't allowed. -TEST_P(AcceleratedSurfaceTransformerTest, Init) { - SCOPED_TRACE(GetAdapterInfo()); - AcceleratedSurfaceTransformer gpu_ops; - ASSERT_TRUE(gpu_ops.Init(device())); - - WarnOnMissingFeatures(&gpu_ops); -}; - -// Fails on some bots because Direct3D isn't allowed. -TEST_P(AcceleratedSurfaceTransformerTest, TestConsistentRandom) { - // This behavior should be the same for every execution on every machine. - // Otherwise tests might be flaky and impossible to debug. - SeedRandom("AcceleratedSurfaceTransformerTest.TestConsistentRandom"); - ASSERT_EQ(2922058934, RandomColor()); - - SeedRandom("AcceleratedSurfaceTransformerTest.TestConsistentRandom"); - ASSERT_EQ(2922058934, RandomColor()); - ASSERT_EQ(4050239976, RandomColor()); - - SeedRandom("DifferentSeed"); - ASSERT_EQ(3904108833, RandomColor()); -} - -// Fails on some bots because Direct3D isn't allowed. -TEST_P(AcceleratedSurfaceTransformerTest, CopyInverted) { - // This behavior should be the same for every execution on every machine. - // Otherwise tests might be flaky and impossible to debug. - SCOPED_TRACE(GetAdapterInfo()); - SeedRandom("CopyInverted"); - - AcceleratedSurfaceTransformer t; - ASSERT_TRUE(t.Init(device())); - - uniform_int_distribution<int> size(1, 512); - - for (int i = 0; i < 100; ++i) { - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&t, gfx::Size(size(rng_), size(rng_)))) - << "At iteration " << i; - } -} - -// Fails on some bots because Direct3D isn't allowed. -// Fails on other bots because of ResizeBilinear symmetry failures. -// Should pass, at least, on NVIDIA Quadro 600. -TEST_P(AcceleratedSurfaceTransformerTest, MixedOperations) { - SCOPED_TRACE(GetAdapterInfo()); - SeedRandom("MixedOperations"); - - AcceleratedSurfaceTransformer t; - ASSERT_TRUE(t.Init(device())); - - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 1)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 2)); - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&t, gfx::Size(20, 107))); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 5)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(64, 64), 5)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&t, gfx::Size(128, 128), 1)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(3, 3), 1)); - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&t, gfx::Size(1412, 124))); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&t, gfx::Size(100, 200), 1)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 1)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 2)); - - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&t, gfx::Size(1512, 7))); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 5)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 256), 8)); - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&t, gfx::Size(1521, 3))); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&t, gfx::Size(140, 181), 1)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 256), 1)); - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&t, gfx::Size(33, 712))); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 8), 8)); - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&t, gfx::Size(33, 2))); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&t, gfx::Size(200, 256), gfx::Size(126, 8), 8)); -} - -// Tests ResizeBilinear with 16K wide/hight src and dst surfaces. -// -// Fails on some bots because Direct3D isn't allowed. -// Should pass, at least, on NVIDIA Quadro 600. -TEST_P(AcceleratedSurfaceTransformerTest, LargeSurfaces) { - SCOPED_TRACE(GetAdapterInfo()); - SeedRandom("LargeSurfaces"); - - AcceleratedSurfaceTransformer gpu_ops; - ASSERT_TRUE(gpu_ops.Init(device())); - - D3DCAPS9 caps; - ASSERT_HRESULT_SUCCEEDED( - device()->GetDeviceCaps(&caps)); - - SCOPED_TRACE(base::StringPrintf( - "max texture size: %dx%d, max texture aspect: %d", - caps.MaxTextureWidth, caps.MaxTextureHeight, caps.MaxTextureAspectRatio)); - - const int w = caps.MaxTextureWidth; - const int h = caps.MaxTextureHeight; - const int lo = 256; - - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&gpu_ops, gfx::Size(w, lo), gfx::Size(lo, lo), 1)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, h), gfx::Size(lo, lo), 1)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, lo), gfx::Size(w, lo), lo)); - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, lo), gfx::Size(lo, h), lo)); - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&gpu_ops, gfx::Size(w, lo))); - ASSERT_NO_FATAL_FAILURE( - DoCopyInvertedTest(&gpu_ops, gfx::Size(lo, h))); - - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(w, lo), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(lo, h), 1)); - -} - -// Exercises ResizeBilinear with random minification cases where the -// aspect ratio does not change. -// -// Fails on some bots because Direct3D isn't allowed. -// Fails on other bots because of StretchRect symmetry failures. -// Should pass, at least, on NVIDIA Quadro 600. -TEST_P(AcceleratedSurfaceTransformerTest, MinifyUniform) { - SCOPED_TRACE(GetAdapterInfo()); - SeedRandom("MinifyUniform"); - - AcceleratedSurfaceTransformer gpu_ops; - ASSERT_TRUE(gpu_ops.Init(device())); - - const int dims[] = {21, 63, 64, 65, 99, 127, 128, 129, 192, 255, 256, 257}; - const int checkerboards[] = {1, 2, 3, 9}; - uniform_int_distribution<int> dim(0, arraysize(dims) - 1); - uniform_int_distribution<int> checkerboard(0, arraysize(checkerboards) - 1); - - for (int i = 0; i < 300; i++) { - // Widths are picked so that dst is smaller than src. - int dst_width = dims[dim(rng_)]; - int src_width = dims[dim(rng_)]; - if (src_width < dst_width) - std::swap(dst_width, src_width); - - // src_height is picked to preserve aspect ratio. - int dst_height = dims[dim(rng_)]; - int src_height = static_cast<int>( - static_cast<int64>(src_width) * dst_height / dst_width); - - int checkerboard_size = checkerboards[checkerboard(rng_)]; - - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&gpu_ops, - gfx::Size(src_width, src_height), // Src size (larger) - gfx::Size(dst_width, dst_height), // Dst size (smaller) - checkerboard_size)) << "Failed on iteration " << i; - } -}; - -// Exercises ResizeBilinear with random magnification cases where the -// aspect ratio does not change. -// -// This test relies on an assertion that resizing preserves symmetry in the -// image, but for the current implementation of ResizeBilinear, this does not -// seem to be true (fails on NVIDIA Quadro 600; passes on -// Intel Mobile 965 Express) -TEST_P(AcceleratedSurfaceTransformerTest, DISABLED_MagnifyUniform) { - SCOPED_TRACE(GetAdapterInfo()); - SeedRandom("MagnifyUniform"); - - AcceleratedSurfaceTransformer gpu_ops; - ASSERT_TRUE(gpu_ops.Init(device())); - - const int dims[] = {63, 64, 65, 99, 127, 128, 129, 192, 255, 256, 257}; - const int checkerboards[] = {1, 2, 3, 9}; - uniform_int_distribution<int> dim(0, arraysize(dims) - 1); - uniform_int_distribution<int> checkerboard(0, arraysize(checkerboards) - 1); - - for (int i = 0; i < 50; i++) { - // Widths are picked so that src is smaller than dst. - int dst_width = dims[dim(rng_)]; - int src_width = dims[dim(rng_)]; - if (dst_width < src_width) - std::swap(src_width, dst_width); - - int dst_height = dims[dim(rng_)]; - int src_height = static_cast<int>( - static_cast<int64>(src_width) * dst_height / dst_width); - - int checkerboard_size = checkerboards[checkerboard(rng_)]; - - ASSERT_NO_FATAL_FAILURE( - DoResizeBilinearTest(&gpu_ops, - gfx::Size(src_width, src_height), // Src size (smaller) - gfx::Size(dst_width, dst_height), // Dst size (larger) - checkerboard_size)) << "Failed on iteration " << i; - } -}; - -TEST_P(AcceleratedSurfaceTransformerTest, RGBtoYUV) { - SeedRandom("RGBtoYUV"); - - AcceleratedSurfaceTransformer gpu_ops; - ASSERT_TRUE(gpu_ops.Init(device())); - - // Start with some easy-to-debug cases. A checkerboard size of 1 is the - // best test, but larger checkerboard sizes give more insight into where - // a bug might be. - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(32, 32), 4)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(32, 32), 2)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(32, 32), 3)); - - // All cases of width (mod 8) and height (mod 8), using 1x1 checkerboard. - for (int w = 32; w < 40; ++w) { - for (int h = 32; h < 40; ++h) { - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(w, h), 1)); - } - } - - // All the very small sizes which require the most shifting in the - // texture coordinates when doing alignment. - for (int w = 1; w <= 9; ++w) { - for (int h = 1; h <= 9; ++h) { - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(w, h), 1)); - } - } - - // Random medium dimensions. - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(10, 142), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(124, 333), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(853, 225), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(231, 412), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(512, 128), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(1024, 768), 1)); - - // Common video/monitor resolutions - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(800, 768), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(1024, 768), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(1280, 720), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(1280, 720), 2)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(1920, 1080), 1)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(1920, 1080), 2)); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionTest(&gpu_ops, gfx::Size(2048, 1536), 1)); -} - -TEST_P(AcceleratedSurfaceTransformerTest, RGBtoYUVScaled) { - SeedRandom("RGBtoYUVScaled"); - - AcceleratedSurfaceTransformer gpu_ops; - ASSERT_TRUE(gpu_ops.Init(device())); - - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionScaleTest(&gpu_ops, gfx::Size(32, 32), gfx::Size(64, 64))); - - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionScaleTest(&gpu_ops, gfx::Size(32, 32), gfx::Size(16, 16))); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionScaleTest(&gpu_ops, gfx::Size(32, 32), gfx::Size(24, 24))); - ASSERT_NO_FATAL_FAILURE( - DoYUVConversionScaleTest(&gpu_ops, gfx::Size(32, 32), gfx::Size(48, 48))); -} - -namespace { - -// Used to suppress test on Windows versions prior to Vista. -std::vector<int> WindowsVersionIfVistaOrBetter() { - std::vector<int> result; - if (base::win::GetVersion() >= base::win::VERSION_VISTA) { - result.push_back(base::win::GetVersion()); - } - return result; -} - -} // namespace - -INSTANTIATE_TEST_CASE_P(VistaAndUp, - AcceleratedSurfaceTransformerTest, - ::testing::ValuesIn(WindowsVersionIfVistaOrBetter())); diff --git a/ui/surface/accelerated_surface_win.cc b/ui/surface/accelerated_surface_win.cc deleted file mode 100644 index d822e95..0000000 --- a/ui/surface/accelerated_surface_win.cc +++ /dev/null @@ -1,1106 +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/surface/accelerated_surface_win.h" - -#include <windows.h> -#include <algorithm> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/command_line.h" -#include "base/debug/trace_event.h" -#include "base/files/file_path.h" -#include "base/lazy_instance.h" -#include "base/metrics/histogram.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/scoped_native_library.h" -#include "base/strings/stringprintf.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "base/threading/thread_restrictions.h" -#include "base/win/wrapped_window_proc.h" -#include "media/base/video_frame.h" -#include "media/base/video_util.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/win/shell.h" -#include "ui/events/latency_info.h" -#include "ui/gfx/frame_time.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/win/dpi.h" -#include "ui/gfx/win/hwnd_util.h" -#include "ui/gl/gl_switches.h" -#include "ui/surface/accelerated_surface_transformer_win.h" -#include "ui/surface/d3d9_utils_win.h" -#include "ui/surface/surface_switches.h" - -namespace d3d_utils = ui_surface_d3d9_utils; - -namespace { - -UINT GetPresentationInterval() { - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) - return D3DPRESENT_INTERVAL_IMMEDIATE; - else - return D3DPRESENT_INTERVAL_ONE; -} - -bool DoFirstShowPresentWithGDI() { - return CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDoFirstShowPresentWithGDI); -} - -bool DoAllShowPresentWithGDI() { - return CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDoAllShowPresentWithGDI); -} - -// Use a SurfaceReader to copy into one plane of the VideoFrame. -bool CopyPlane(AcceleratedSurfaceTransformer* gpu_ops, - IDirect3DSurface9* src_surface, - media::VideoFrame* dst_frame, - size_t plane_id) { - int width_in_bytes = dst_frame->row_bytes(plane_id); - return gpu_ops->ReadFast(src_surface, dst_frame->data(plane_id), - width_in_bytes, dst_frame->rows(plane_id), - dst_frame->row_bytes(plane_id)); -} - -} // namespace - -// 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: - PresentThread(const char* name, uint64 adapter_luid); - - IDirect3DDevice9Ex* device() { return device_.get(); } - IDirect3DQuery9* query() { return query_.get(); } - AcceleratedSurfaceTransformer* surface_transformer() { - return &surface_transformer_; - } - - void SetAdapterLUID(uint64 adapter_luid); - void InitDevice(); - void LockAndResetDevice(); - void ResetDevice(); - bool IsDeviceLost(); - - base::Lock* lock() { - return &lock_; - } - - protected: - virtual void Init(); - virtual void CleanUp(); - - private: - friend class base::RefCountedThreadSafe<PresentThread>; - - ~PresentThread(); - - // The lock is taken while any thread is calling an AcceleratedPresenter - // associated with this thread. - base::Lock lock_; - - base::ScopedNativeLibrary d3d_module_; - uint64 adapter_luid_; - 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_; - AcceleratedSurfaceTransformer surface_transformer_; - - 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(); - - void SetAdapterLUID(uint64 adapter_luid); - - private: - base::Lock lock_; - int next_thread_; - scoped_refptr<PresentThread> present_threads_[kNumPresentThreads]; - uint64 adapter_luid_; - - 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::PluginWindowHandle window); - void RemovePresenter(const scoped_refptr<AcceleratedPresenter>& presenter); - scoped_refptr<AcceleratedPresenter> GetPresenter( - gfx::PluginWindowHandle window); - - // Destroy any D3D resources owned by the given present thread. Called on - // the given present thread. - void ResetPresentThread(PresentThread* present_thread); - - private: - base::Lock lock_; - typedef std::map<gfx::PluginWindowHandle, AcceleratedPresenter*> PresenterMap; - PresenterMap presenters_; - uint64 adapter_luid_; - 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, uint64 adapter_luid) - : base::Thread(name), - adapter_luid_(adapter_luid) { -} - -void PresentThread::SetAdapterLUID(uint64 adapter_luid) { - base::AutoLock locked(lock_); - - CHECK(message_loop() == base::MessageLoop::current()); - - if (adapter_luid_ == adapter_luid) - return; - - adapter_luid_ = adapter_luid; - if (device_) - ResetDevice(); -} - -void PresentThread::InitDevice() { - lock_.AssertAcquired(); - - if (device_) - return; - - TRACE_EVENT0("gpu", "PresentThread::Init"); - d3d_utils::LoadD3D9(&d3d_module_); - ResetDevice(); -} - -void PresentThread::LockAndResetDevice() { - base::AutoLock locked(lock_); - ResetDevice(); -} - -void PresentThread::ResetDevice() { - TRACE_EVENT0("gpu", "PresentThread::ResetDevice"); - - lock_.AssertAcquired(); - - // The D3D device must be created on the present thread. - CHECK(message_loop() == base::MessageLoop::current()); - - // This will crash some Intel drivers but we can't render anything without - // reseting the device, which would be disappointing. - query_ = NULL; - device_ = NULL; - surface_transformer_.ReleaseAll(); - - g_accelerated_presenter_map.Pointer()->ResetPresentThread(this); - - if (!d3d_utils::CreateDevice(d3d_module_, - adapter_luid_, - D3DDEVTYPE_HAL, - GetPresentationInterval(), - device_.Receive())) { - return; - } - - HRESULT hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to create query"; - device_ = NULL; - return; - } - - if (!surface_transformer_.Init(device_)) { - LOG(ERROR) << "Failed to initialize surface transformer"; - query_ = NULL; - device_ = NULL; - return; - } -} - -bool PresentThread::IsDeviceLost() { - lock_.AssertAcquired(); - - HRESULT hr = device_->CheckDeviceState(NULL); - return FAILED(hr) || hr == S_PRESENT_MODE_CHANGED; -} - -void PresentThread::Init() { - TRACE_EVENT0("gpu", "Initialize thread"); -} - -void PresentThread::CleanUp() { - // The D3D device and query are leaked because destroying the associated D3D - // query crashes some Intel drivers. - surface_transformer_.DetachAll(); - device_.Detach(); - query_.Detach(); -} - -PresentThread::~PresentThread() { - Stop(); -} - -PresentThreadPool::PresentThreadPool() : next_thread_(0) { -} - -PresentThread* PresentThreadPool::NextThread() { - base::AutoLock locked(lock_); - - next_thread_ = (next_thread_ + 1) % kNumPresentThreads; - PresentThread* thread = present_threads_[next_thread_].get(); - if (!thread) { - thread = new PresentThread( - base::StringPrintf("PresentThread #%d", next_thread_).c_str(), - adapter_luid_); - thread->Start(); - present_threads_[next_thread_] = thread; - } - - return thread; -} - -void PresentThreadPool::SetAdapterLUID(uint64 adapter_luid) { - base::AutoLock locked(lock_); - - adapter_luid_ = adapter_luid; - - for (int i = 0; i < kNumPresentThreads; ++i) { - if (!present_threads_[i]) - continue; - - present_threads_[i]->message_loop()->PostTask( - FROM_HERE, - base::Bind(&PresentThread::SetAdapterLUID, - present_threads_[i], - adapter_luid)); - } -} - -AcceleratedPresenterMap::AcceleratedPresenterMap() { -} - -scoped_refptr<AcceleratedPresenter> AcceleratedPresenterMap::CreatePresenter( - gfx::PluginWindowHandle 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::PluginWindowHandle window) { - base::AutoLock locked(lock_); - PresenterMap::iterator it = presenters_.find(window); - if (it == presenters_.end()) - return scoped_refptr<AcceleratedPresenter>(); - - return it->second; -} - -void AcceleratedPresenterMap::ResetPresentThread( - PresentThread* present_thread) { - base::AutoLock locked(lock_); - - for (PresenterMap::iterator it = presenters_.begin(); - it != presenters_.end(); - ++it) { - it->second->ResetPresentThread(present_thread); - } -} - -AcceleratedPresenter::AcceleratedPresenter(gfx::PluginWindowHandle window) - : present_thread_(g_present_thread_pool.Pointer()->NextThread()), - window_(window), - event_(false, false), - hidden_(true), - do_present_with_GDI_(DoAllShowPresentWithGDI() || - DoFirstShowPresentWithGDI()), - is_session_locked_(false) { -} - -// static -void AcceleratedPresenter::SetAdapterLUID(uint64 adapter_luid) { - return g_present_thread_pool.Pointer()->SetAdapterLUID(adapter_luid); -} - - -// static -scoped_refptr<AcceleratedPresenter> AcceleratedPresenter::GetForWindow( - gfx::PluginWindowHandle window) { - return g_accelerated_presenter_map.Pointer()->GetPresenter(window); -} - -void AcceleratedPresenter::AsyncPresentAndAcknowledge( - const gfx::Size& size, - int64 surface_handle, - const std::vector<ui::LatencyInfo>& latency_info, - const CompletionTask& completion_task) { - if (!surface_handle) { - TRACE_EVENT1("gpu", "EarlyOut_ZeroSurfaceHandle", - "surface_handle", surface_handle); - completion_task.Run(true, base::TimeTicks(), base::TimeDelta(), - std::vector<ui::LatencyInfo>()); - return; - } - - present_thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge, - this, - size, - surface_handle, - latency_info, - completion_task)); -} - -void AcceleratedPresenter::Present(HDC dc) { - TRACE_EVENT0("gpu", "Present"); - - base::AutoLock locked(*present_thread_->lock()); - - // If invalidated, do nothing. The window is gone. - if (!window_) - return; - - // Suspended or nothing has ever been presented. - if (!swap_chain_) - return; - - PresentWithGDI(dc); -} - -void AcceleratedPresenter::AsyncCopyTo( - const gfx::Rect& requested_src_subrect, - const gfx::Size& dst_size, - const base::Callback<void(bool, const SkBitmap&)>& callback) { - present_thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&AcceleratedPresenter::DoCopyToAndAcknowledge, - this, - requested_src_subrect, - dst_size, - base::MessageLoopProxy::current(), - callback)); -} - -void AcceleratedPresenter::AsyncCopyToVideoFrame( - const gfx::Rect& requested_src_subrect, - const scoped_refptr<media::VideoFrame>& target, - const base::Callback<void(bool)>& callback) { - present_thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&AcceleratedPresenter::DoCopyToVideoFrameAndAcknowledge, - this, - requested_src_subrect, - target, - base::MessageLoopProxy::current(), - callback)); -} - -void AcceleratedPresenter::DoCopyToAndAcknowledge( - const gfx::Rect& src_subrect, - const gfx::Size& dst_size, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner, - const base::Callback<void(bool, const SkBitmap&)>& callback) { - SkBitmap target; - bool result = DoCopyToARGB(src_subrect, dst_size, &target); - if (!result) - target.reset(); - callback_runner->PostTask(FROM_HERE, base::Bind(callback, result, target)); -} - -void AcceleratedPresenter::DoCopyToVideoFrameAndAcknowledge( - const gfx::Rect& src_subrect, - const scoped_refptr<media::VideoFrame>& target, - const scoped_refptr<base::SingleThreadTaskRunner>& callback_runner, - const base::Callback<void(bool)>& callback) { - - bool result = DoCopyToYUV(src_subrect, target); - callback_runner->PostTask(FROM_HERE, base::Bind(callback, result)); -} - -bool AcceleratedPresenter::DoCopyToARGB(const gfx::Rect& requested_src_subrect, - const gfx::Size& dst_size, - SkBitmap* bitmap) { - TRACE_EVENT2( - "gpu", "CopyTo", - "width", dst_size.width(), - "height", dst_size.height()); - - base::AutoLock locked(*present_thread_->lock()); - - if (!swap_chain_) - return false; - - AcceleratedSurfaceTransformer* gpu_ops = - present_thread_->surface_transformer(); - - base::win::ScopedComPtr<IDirect3DSurface9> back_buffer; - HRESULT hr = swap_chain_->GetBackBuffer(0, - D3DBACKBUFFER_TYPE_MONO, - back_buffer.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get back buffer"; - return false; - } - - D3DSURFACE_DESC desc; - hr = back_buffer->GetDesc(&desc); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get buffer description"; - return false; - } - - const gfx::Size back_buffer_size(desc.Width, desc.Height); - if (back_buffer_size.IsEmpty()) - return false; - - // With window resizing, it's possible that the back buffer is smaller than - // the requested src subset. Clip to the actual back buffer. - gfx::Rect src_subrect = requested_src_subrect; - src_subrect.Intersect(gfx::Rect(back_buffer_size)); - base::win::ScopedComPtr<IDirect3DSurface9> final_surface; - { - if (!d3d_utils::CreateOrReuseLockableSurface(present_thread_->device(), - dst_size, - &final_surface)) { - LOG(ERROR) << "Failed to create temporary lockable surface"; - return false; - } - } - - { - // Let the surface transformer start the resize into |final_surface|. - TRACE_EVENT0("gpu", "ResizeBilinear"); - if (!gpu_ops->ResizeBilinear(back_buffer, src_subrect, - final_surface, gfx::Rect(dst_size))) { - LOG(ERROR) << "Failed to resize bilinear"; - return false; - } - } - - bitmap->setConfig(SkBitmap::kARGB_8888_Config, dst_size.width(), - dst_size.height(), 0, kOpaque_SkAlphaType); - if (!bitmap->allocPixels()) - return false; - - // Copy |final_surface| to |bitmap|. This is always a synchronous operation. - return gpu_ops->ReadFast(final_surface, - reinterpret_cast<uint8*>(bitmap->getPixels()), - bitmap->width() * bitmap->bytesPerPixel(), - bitmap->height(), - static_cast<int>(bitmap->rowBytes())); -} - -bool AcceleratedPresenter::DoCopyToYUV( - const gfx::Rect& requested_src_subrect, - const scoped_refptr<media::VideoFrame>& frame) { - gfx::Size dst_size = frame->coded_size(); - TRACE_EVENT2( - "gpu", "CopyToYUV", - "width", dst_size.width(), - "height", dst_size.height()); - - base::AutoLock locked(*present_thread_->lock()); - - if (!swap_chain_) - return false; - - AcceleratedSurfaceTransformer* gpu_ops = - present_thread_->surface_transformer(); - - 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; - - // With window resizing, it's possible that the back buffer is smaller than - // the requested src subset. Clip to the actual back buffer. - gfx::Rect src_subrect = requested_src_subrect; - src_subrect.Intersect(gfx::Rect(back_buffer_size)); - if (src_subrect.IsEmpty()) - return false; - - base::win::ScopedComPtr<IDirect3DSurface9> resized; - base::win::ScopedComPtr<IDirect3DTexture9> resized_as_texture; - if (!gpu_ops->GetIntermediateTexture(dst_size, - resized_as_texture.Receive(), - resized.Receive())) { - return false; - } - - // Shrink the source to fit entirely in the destination while preserving - // aspect ratio. Fill in any margin with black. - // TODO(nick): It would be more efficient all around to implement - // letterboxing as a memset() on the dst. - gfx::Rect letterbox = media::ComputeLetterboxRegion(gfx::Rect(dst_size), - src_subrect.size()); - if (letterbox != gfx::Rect(dst_size)) { - TRACE_EVENT0("gpu", "Letterbox"); - present_thread_->device()->ColorFill(resized, NULL, 0xFF000000); - } - - { - TRACE_EVENT0("gpu", "ResizeBilinear"); - if (!gpu_ops->ResizeBilinear(back_buffer, src_subrect, resized, letterbox)) - return false; - } - - base::win::ScopedComPtr<IDirect3DSurface9> y, u, v; - { - TRACE_EVENT0("gpu", "TransformRGBToYV12"); - if (!gpu_ops->TransformRGBToYV12(resized_as_texture, - dst_size, - y.Receive(), u.Receive(), v.Receive())) { - return false; - } - } - - if (!CopyPlane(gpu_ops, y, frame, media::VideoFrame::kYPlane)) - return false; - if (!CopyPlane(gpu_ops, u, frame, media::VideoFrame::kUPlane)) - return false; - if (!CopyPlane(gpu_ops, v, frame, media::VideoFrame::kVPlane)) - return false; - return true; -} - -void AcceleratedPresenter::Suspend() { - present_thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&AcceleratedPresenter::DoSuspend, - this)); -} - -void AcceleratedPresenter::WasHidden() { - base::AutoLock locked(*present_thread_->lock()); - hidden_ = true; -} - -void AcceleratedPresenter::ReleaseSurface() { - present_thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&AcceleratedPresenter::DoReleaseSurface, - this)); -} - -void AcceleratedPresenter::SetIsSessionLocked(bool locked) { - is_session_locked_ = locked; -} - -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(*present_thread_->lock()); - window_ = NULL; -} - -void AcceleratedPresenter::ResetPresentThread( - PresentThread* present_thread) { - TRACE_EVENT0("gpu", "ResetPresentThread"); - - // present_thread_ can be accessed without the lock because it is immutable. - if (present_thread_ != present_thread) - return; - - present_thread_->lock()->AssertAcquired(); - - source_texture_ = NULL; - swap_chain_ = NULL; - quantized_size_ = gfx::Size(); -} - -AcceleratedPresenter::~AcceleratedPresenter() { -} - -bool AcceleratedPresenter::IsSwapChainInitialized() const { - base::AutoLock locked(*present_thread_->lock()); - - return !!swap_chain_; -} - -void AcceleratedPresenter::DoPresentAndAcknowledge( - const gfx::Size& size, - int64 surface_handle, - const std::vector<ui::LatencyInfo>& latency_info, - const CompletionTask& completion_task) { - TRACE_EVENT2( - "gpu", "DoPresentAndAcknowledge", - "width", size.width(), - "height", size.height()); - - HRESULT hr; - - base::AutoLock locked(*present_thread_->lock()); - - for (size_t i = 0; i < latency_info.size(); i++) - latency_info_.push_back(latency_info[i]); - - // Initialize the device lazily since calling Direct3D can crash bots. - present_thread_->InitDevice(); - - if (!present_thread_->device()) { - completion_task.Run(false, base::TimeTicks(), base::TimeDelta(), - std::vector<ui::LatencyInfo>()); - TRACE_EVENT0("gpu", "EarlyOut_NoDevice"); - return; - } - - // Ensure the task is acknowledged on early out after this point. - base::ScopedClosureRunner scoped_completion_runner( - base::Bind(completion_task, - true, - base::TimeTicks(), - base::TimeDelta(), - std::vector<ui::LatencyInfo>())); - - // If invalidated, do nothing, the window is gone. - if (!window_) { - TRACE_EVENT0("gpu", "EarlyOut_NoWindow"); - return; - } - -#if !defined(USE_AURA) - // If the window is a different size than the swap chain that is being - // presented then drop the frame. - gfx::Size window_size = GetWindowSize(); - bool size_mismatch = size != window_size; - if (gfx::IsInHighDPIMode()) { - // Check if the size mismatch is within allowable round off or truncation - // error. - gfx::Size dip_size = gfx::win::ScreenToDIPSize(window_size); - gfx::Size pixel_size = gfx::win::DIPToScreenSize(dip_size); - size_mismatch = abs(window_size.width() - size.width()) > - abs(window_size.width() - pixel_size.width()) || - abs(window_size.height() - size.height()) > - abs(window_size.height() - pixel_size.height()); - } - if (hidden_ && size_mismatch) { - TRACE_EVENT2("gpu", "EarlyOut_WrongWindowSize", - "backwidth", size.width(), "backheight", size.height()); - TRACE_EVENT2("gpu", "EarlyOut_WrongWindowSize2", - "windowwidth", window_size.width(), - "windowheight", window_size.height()); - return; - } -#endif - // 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_ || quantized_size_ != quantized_size) { - TRACE_EVENT0("gpu", "CreateAdditionalSwapChain"); - quantized_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 = window_; - 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)) { - LOG(ERROR) << "Failed to create swap chain " - << quantized_size.width() << " x " <<quantized_size.height(); - return; - } - } - - if (!source_texture_.get()) { - TRACE_EVENT0("gpu", "OpenSharedTexture"); - if (!d3d_utils::OpenSharedTexture(present_thread_->device(), - surface_handle, - size, - source_texture_.Receive())) { - LOG(ERROR) << "Failed to open shared texture"; - return; - } - } - - base::win::ScopedComPtr<IDirect3DSurface9> source_surface; - hr = source_texture_->GetSurfaceLevel(0, source_surface.Receive()); - if (FAILED(hr)) { - TRACE_EVENT0("gpu", "EarlyOut_NoSurfaceLevel"); - LOG(ERROR) << "Failed to get source surface"; - return; - } - - base::win::ScopedComPtr<IDirect3DSurface9> dest_surface; - hr = swap_chain_->GetBackBuffer(0, - D3DBACKBUFFER_TYPE_MONO, - dest_surface.Receive()); - if (FAILED(hr)) { - TRACE_EVENT0("gpu", "EarlyOut_NoBackbuffer"); - LOG(ERROR) << "Failed to get back buffer"; - return; - } - - RECT rect = { - 0, 0, - size.width(), size.height() - }; - - { - TRACE_EVENT0("gpu", "Copy"); - - // Copy while flipping the source texture on the vertical axis. - bool result = present_thread_->surface_transformer()->CopyInverted( - source_texture_, dest_surface, size); - if (!result) { - LOG(ERROR) << "Failed to copy shared texture"; - return; - } - } - - hr = present_thread_->query()->Issue(D3DISSUE_END); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to issue query"; - return; - } - - present_size_ = size; - - // If it is expected that Direct3D cannot be used reliably because the window - // is resizing, fall back to presenting with GDI. - if (CheckDirect3DWillWork()) { - TRACE_EVENT0("gpu", "PresentD3D"); - - hr = swap_chain_->Present(&rect, &rect, window_, NULL, 0); - - if (FAILED(hr)) { - if (present_thread_->IsDeviceLost()) - present_thread_->ResetDevice(); - return; - } - } else { - HDC dc = GetDC(window_); - PresentWithGDI(dc); - ReleaseDC(window_, dc); - } - - hidden_ = false; - - D3DDISPLAYMODE display_mode; - hr = present_thread_->device()->GetDisplayMode(0, &display_mode); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get display mode"; - return; - } - - D3DRASTER_STATUS raster_status; - hr = swap_chain_->GetRasterStatus(&raster_status); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get raster status"; - return; - } - - UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.AcceleratedSurfaceRefreshRate", - display_mode.RefreshRate, 0, 121, 122); - - // I can't figure out how to determine how many scanlines are in the - // vertical blank so clamp it such that scanline / height <= 1. - int clamped_scanline = std::min(raster_status.ScanLine, display_mode.Height); - - // The Internet says that on some GPUs, the scanline is not available - // while in the vertical blank. - if (raster_status.InVBlank) - clamped_scanline = display_mode.Height; - - // Figure out approximately how far back in time the last vsync was based on - // the ratio of the raster scanline to the display height. - base::TimeTicks last_vsync_time; - base::TimeDelta refresh_period; - - if (display_mode.Height) { - refresh_period = base::TimeDelta::FromMicroseconds( - 1000000 / display_mode.RefreshRate); - // If FrameTime is not high resolution, we use a timebase of zero to avoid - // introducing jitter into our frame start times. - if (gfx::FrameTime::TimestampsAreHighRes()) { - base::TimeTicks current_time = gfx::FrameTime::Now(); - last_vsync_time = current_time - - base::TimeDelta::FromMilliseconds((clamped_scanline * 1000) / - (display_mode.RefreshRate * display_mode.Height)); - } - } - - // Wait for the StretchRect to complete before notifying the GPU process - // that it is safe to write to its backing store again. - { - TRACE_EVENT0("gpu", "spin"); - - do { - hr = present_thread_->query()->GetData(NULL, 0, D3DGETDATA_FLUSH); - if (hr == S_FALSE) { - Sleep(1); - - if (present_thread_->IsDeviceLost()) { - present_thread_->ResetDevice(); - return; - } - } - } while (hr == S_FALSE); - } - - scoped_completion_runner.Release(); - completion_task.Run(true, last_vsync_time, refresh_period, latency_info_); - latency_info_.clear(); -} - -void AcceleratedPresenter::DoSuspend() { - base::AutoLock locked(*present_thread_->lock()); - swap_chain_ = NULL; -} - -void AcceleratedPresenter::DoReleaseSurface() { - base::AutoLock locked(*present_thread_->lock()); - present_thread_->InitDevice(); - source_texture_.Release(); -} - -void AcceleratedPresenter::PresentWithGDI(HDC dc) { - TRACE_EVENT0("gpu", "PresentWithGDI"); - - if (!present_thread_->device()) { - LOG(ERROR) << "No device"; - return; - } - - if (!swap_chain_) { - LOG(ERROR) << "No swap chain"; - return; - } - - base::win::ScopedComPtr<IDirect3DTexture9> system_texture; - { - TRACE_EVENT0("gpu", "CreateSystemTexture"); - HRESULT hr = present_thread_->device()->CreateTexture( - quantized_size_.width(), - quantized_size_.height(), - 1, - 0, - D3DFMT_A8R8G8B8, - D3DPOOL_SYSTEMMEM, - system_texture.Receive(), - NULL); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to create system memory texture"; - return; - } - } - - base::win::ScopedComPtr<IDirect3DSurface9> system_surface; - HRESULT hr = system_texture->GetSurfaceLevel(0, system_surface.Receive()); - DCHECK(SUCCEEDED(hr)); - - base::win::ScopedComPtr<IDirect3DSurface9> back_buffer; - hr = swap_chain_->GetBackBuffer(0, - D3DBACKBUFFER_TYPE_MONO, - back_buffer.Receive()); - DCHECK(SUCCEEDED(hr)); - - { - TRACE_EVENT0("gpu", "GetRenderTargetData"); - hr = present_thread_->device()->GetRenderTargetData(back_buffer, - system_surface); - - if (FAILED(hr)) { - if (present_thread_->IsDeviceLost()) { - present_thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&PresentThread::LockAndResetDevice, present_thread_)); - } - return; - } - - DCHECK(SUCCEEDED(hr)); - } - - D3DLOCKED_RECT locked_surface; - hr = system_surface->LockRect(&locked_surface, NULL, D3DLOCK_READONLY); - DCHECK(SUCCEEDED(hr)); - - BITMAPINFO bitmap_info = { - { - sizeof(BITMAPINFOHEADER), - quantized_size_.width(), - -quantized_size_.height(), - 1, // planes - 32, // bitcount - BI_RGB - }, - { - {0, 0, 0, 0} - } - }; - - { - TRACE_EVENT0("gpu", "StretchDIBits"); - StretchDIBits(dc, - 0, 0, - present_size_.width(), - present_size_.height(), - 0, 0, - present_size_.width(), - present_size_.height(), - locked_surface.pBits, - &bitmap_info, - DIB_RGB_COLORS, - SRCCOPY); - } - - system_surface->UnlockRect(); -} - -gfx::Size AcceleratedPresenter::GetWindowSize() { - RECT rect; - GetClientRect(window_, &rect); - return gfx::Rect(rect).size(); -} - -bool AcceleratedPresenter::CheckDirect3DWillWork() { - // On a composited desktop, when the screen saver or logon screen are - // active, D3D presents never make it to the window but GDI presents - // do. If the session is locked GDI presents can be avoided since - // the window gets a message on unlock and forces a repaint. - if (!is_session_locked_ && ui::win::IsAeroGlassEnabled()) { - // Failure to open the input desktop is a sign of running with a non-default - // desktop. - HDESK input_desktop = ::OpenInputDesktop(0, 0, GENERIC_READ); - if (!input_desktop) - return false; - ::CloseDesktop(input_desktop); - } - - gfx::Size window_size = GetWindowSize(); - if (window_size != last_window_size_ && last_window_size_.GetArea() != 0) { - last_window_size_ = window_size; - last_window_resize_time_ = base::Time::Now(); - return false; - } - - if (do_present_with_GDI_ && hidden_) { - if (DoFirstShowPresentWithGDI()) - do_present_with_GDI_ = false; - - return false; - } - - return base::Time::Now() - last_window_resize_time_ > - base::TimeDelta::FromMilliseconds(100); -} - -AcceleratedSurface::AcceleratedSurface(gfx::PluginWindowHandle window) - : presenter_(g_accelerated_presenter_map.Pointer()->CreatePresenter( - window)) { -} - -AcceleratedSurface::~AcceleratedSurface() { - g_accelerated_presenter_map.Pointer()->RemovePresenter(presenter_); - presenter_->Invalidate(); -} - -void AcceleratedSurface::Present(HDC dc) { - presenter_->Present(dc); -} - -bool AcceleratedSurface::IsReadyForCopy() const { - return !!presenter_ && presenter_->IsSwapChainInitialized(); -} - - -void AcceleratedSurface::AsyncCopyTo( - const gfx::Rect& src_subrect, - const gfx::Size& dst_size, - const base::Callback<void(bool, const SkBitmap&)>& callback) { - presenter_->AsyncCopyTo(src_subrect, dst_size, callback); -} - -void AcceleratedSurface::AsyncCopyToVideoFrame( - const gfx::Rect& src_subrect, - const scoped_refptr<media::VideoFrame>& target, - const base::Callback<void(bool)>& callback) { - presenter_->AsyncCopyToVideoFrame(src_subrect, target, callback); -} - -void AcceleratedSurface::Suspend() { - presenter_->Suspend(); -} - -void AcceleratedSurface::WasHidden() { - presenter_->WasHidden(); -} - -void AcceleratedSurface::SetIsSessionLocked(bool locked) { - presenter_->SetIsSessionLocked(locked); -} diff --git a/ui/surface/accelerated_surface_win.h b/ui/surface/accelerated_surface_win.h deleted file mode 100644 index 9615732..0000000 --- a/ui/surface/accelerated_surface_win.h +++ /dev/null @@ -1,223 +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. - -#ifndef UI_SURFACE_ACCELERATED_SURFACE_WIN_H_ -#define UI_SURFACE_ACCELERATED_SURFACE_WIN_H_ - -#include <d3d9.h> - -#include "base/callback_forward.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/time/time.h" -#include "base/win/scoped_comptr.h" -#include "ui/events/latency_info.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/size.h" -#include "ui/surface/surface_export.h" - -class PresentThread; - -namespace gfx { -class Rect; -} - -namespace media { -class VideoFrame; -} - -class SURFACE_EXPORT AcceleratedPresenter - : public base::RefCountedThreadSafe<AcceleratedPresenter> { - public: - typedef base::Callback<void( - bool, - base::TimeTicks, - base::TimeDelta, - const std::vector<ui::LatencyInfo>&)> CompletionTask; - - explicit AcceleratedPresenter(gfx::PluginWindowHandle window); - - static void SetAdapterLUID(uint64 adapter_luid); - - // Returns a thread safe reference to the presenter for the given window or - // null is no such presenter exists. The thread safe refptr ensures the - // presenter will not be destroyed. This can be called on any thread. - static scoped_refptr<AcceleratedPresenter> GetForWindow( - gfx::PluginWindowHandle window); - - // Schedule a frame to be presented. The completion callback will be invoked - // when it is safe to write to the surface on another thread. The lock for - // this surface will be held while the completion callback runs. This can be - // called on any thread. - void AsyncPresentAndAcknowledge( - const gfx::Size& size, - int64 surface_handle, - const std::vector<ui::LatencyInfo>& latency_info, - const CompletionTask& completion_task); - - // Returns true if the swap chain has been created and initialized. This can - // be called on any thread. - bool IsSwapChainInitialized() const; - - // Schedule the presenter to free all its resources. This can be called on any - // thread. - void Suspend(); - - // Indicates that the presenter has become invisible. - void WasHidden(); - - // Called when the Windows session is locked or unlocked. - void SetIsSessionLocked(bool locked); - - // Schedule the presenter to release its reference to the shared surface. - void ReleaseSurface(); - - // The public member functions are called on the main thread. - void Present(HDC dc); - void AsyncCopyTo(const gfx::Rect& src_subrect, - const gfx::Size& dst_size, - const base::Callback<void(bool, const SkBitmap&)>& callback); - void AsyncCopyToVideoFrame( - const gfx::Rect& src_subrect, - const scoped_refptr<media::VideoFrame>& target, - const base::Callback<void(bool)>& callback); - void Invalidate(); - - // Destroy any D3D resources owned by the given present thread. Called on - // the given present thread. - void ResetPresentThread(PresentThread* present_thread); - - private: - friend class base::RefCountedThreadSafe<AcceleratedPresenter>; - - ~AcceleratedPresenter(); - - // These member functions are called on the PresentThread with which the - // presenter has affinity. - void DoPresentAndAcknowledge( - const gfx::Size& size, - int64 surface_handle, - const std::vector<ui::LatencyInfo>& latency_info, - const CompletionTask& completion_task); - void DoSuspend(); - void DoPresent(const base::Closure& composite_task); - void DoReleaseSurface(); - void DoCopyToAndAcknowledge( - const gfx::Rect& src_subrect, - const gfx::Size& dst_size, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner, - const base::Callback<void(bool, const SkBitmap&)>& callback); - void DoCopyToVideoFrameAndAcknowledge( - const gfx::Rect& src_subrect, - const scoped_refptr<media::VideoFrame>& target, - const scoped_refptr<base::SingleThreadTaskRunner>& callback_runner, - const base::Callback<void(bool)>& callback); - bool DoCopyToYUV(const gfx::Rect& src_subrect, - const scoped_refptr<media::VideoFrame>& frame); - bool DoCopyToARGB(const gfx::Rect& src_subrect, - const gfx::Size& dst_size, - SkBitmap* bitmap); - - void PresentWithGDI(HDC dc); - gfx::Size GetWindowSize(); - - // This function tries to guess whether Direct3D will be able to reliably - // present to the window. When the window is resizing, presenting with - // Direct3D causes other regions of the window rendered with GDI to - // flicker transparent / non-transparent. - bool CheckDirect3DWillWork(); - - // The thread with which this presenter has affinity. - PresentThread* const present_thread_; - - // The window that is presented to. - gfx::PluginWindowHandle window_; - - // UI thread can wait on this event to ensure a present is finished. - base::WaitableEvent event_; - - // The current size of the swap chain. This is only accessed on the thread - // with which the surface has affinity. The swap chain size is rounded up and - // is not necessarily the same as the window size. - gfx::Size quantized_size_; - - // The size of the window on the last present. This is used to trigger the - // compositor instead of presenting the last frame in the case where the - // window has been resized. - gfx::Size present_size_; - - // This is a shared texture that is being presented from. - base::win::ScopedComPtr<IDirect3DTexture9> source_texture_; - - // The swap chain is presented to the child window. Copy semantics - // are used so it is possible to represent it to quickly validate the window. - base::win::ScopedComPtr<IDirect3DSwapChain9> swap_chain_; - - // Whether the window is hidden or has not been presented to since it was - // last hidden. - bool hidden_; - - // Set to true if the first present after the tab is unhidden needs to be done - // with GDI. - bool do_present_with_GDI_; - - // Set to true when the Windows session is locked. - bool is_session_locked_; - - // These are used to detect when the window is resizing. For some reason, - // presenting with D3D while the window resizes causes those parts not - // drawn with D3D (e.g. with GDI) to flicker visible / invisible. - // http://crbug.com/120904 - gfx::Size last_window_size_; - base::Time last_window_resize_time_; - - std::vector<ui::LatencyInfo> latency_info_; - - DISALLOW_COPY_AND_ASSIGN(AcceleratedPresenter); -}; - -class SURFACE_EXPORT AcceleratedSurface { - public: - AcceleratedSurface(gfx::PluginWindowHandle window); - ~AcceleratedSurface(); - - // Synchronously present a frame with no acknowledgement. - void Present(HDC dc); - - // Returns true if the surface is fully initialized and has been presented to - // at least once. - bool IsReadyForCopy() const; - - // Transfer the contents of the surface to an SkBitmap, and invoke a callback - // with the result. - void AsyncCopyTo(const gfx::Rect& src_subrect, - const gfx::Size& dst_size, - const base::Callback<void(bool, const SkBitmap&)>& callback); - - // Transfer the contents of the surface to an already-allocated YV12 - // VideoFrame, and invoke a callback to indicate success or failure. - void AsyncCopyToVideoFrame( - const gfx::Rect& src_subrect, - const scoped_refptr<media::VideoFrame>& target, - const base::Callback<void(bool)>& callback); - - // Temporarily release resources until a new surface is asynchronously - // presented. Present will not be able to represent the last surface after - // calling this and will return false. - void Suspend(); - - // Indicates that the surface has become invisible. - void WasHidden(); - - // Called when the Windows session in locked or unlocked. - void SetIsSessionLocked(bool locked); - - private: - const scoped_refptr<AcceleratedPresenter> presenter_; - DISALLOW_COPY_AND_ASSIGN(AcceleratedSurface); -}; - -#endif // UI_SURFACE_ACCELERATED_SURFACE_WIN_H_ diff --git a/ui/surface/compile_hlsl.py b/ui/surface/compile_hlsl.py deleted file mode 100644 index 3584804..0000000 --- a/ui/surface/compile_hlsl.py +++ /dev/null @@ -1,161 +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. - -import optparse -import os.path -import re -import subprocess -import sys - - -def ConvertToCamelCase(input): - """Converts the input string from 'unix_hacker' style to 'CamelCase' style.""" - return ''.join(x[:1].upper() + x[1:] for x in input.split('_')) - - -def ExtractShaderTargetNamesFromSource(source_hlsl_file): - """Parses '@gyp_compile' and '@gyp_namespace' metadata from an .hlsl file.""" - # matches strings like // @gyp_compile(arg_a, arg_b) ... - gyp_compile = re.compile( - '^//\s*@gyp_compile\(\s*(?P<profile>[a-zA-Z0-9_]+)\s*,' - '\s*(?P<function_name>[a-zA-Z0-9_]+)\s*\).*') - # matches strings like // @gyp_namespace(arg_a) ... - gyp_namespace = re.compile( - '^//\s*@gyp_namespace\(\s*(?P<namespace>[a-zA-Z0-9_]+)\s*\).*') - - shader_targets = [] # tuples like ('vs_2_0', 'vertexMain') - namespace = None - with open(source_hlsl_file) as hlsl: - for line_number, line in enumerate(hlsl.read().splitlines(), 1): - m = gyp_compile.match(line) - if m: - shader_targets.append((m.group('profile'), m.group('function_name'))) - continue - m = gyp_namespace.match(line) - if m: - namespace = m.group('namespace') - continue - if '@gyp' in line: - print '%s(%d) : warning: ignoring malformed @gyp directive ' % ( - source_hlsl_file, line_number) - - if not shader_targets: - print ( -"""%s(%d) : error: Reached end of file without finding @gyp_compile directive. - - By convention, each HLSL source must contain one or more @gyp_compile - directives in its comments, as metadata informing the Chrome build tool - which entry points should be compiled. For example, to specify compilation - of a function named 'vertexMain' as a shader model 2 vertex shader: - - // @gyp_compile(vs_2_0, vertexMain) - - Or to compile a pixel shader 2.0 function named 'someOtherShader': - - // @gyp_compile(ps_2_0, someOtherShader) - - To wrap everything in a C++ namespace 'foo_bar', add a line somewhere like: - - // @gyp_namespace(foo_bar) - - (Namespaces are optional) -""" % (source_hlsl_file, line_number)) - sys.exit(1) - return (shader_targets, namespace) - - -def GetCppVariableName(function_name): - return 'k%s' % ConvertToCamelCase(function_name) - - -def CompileMultipleHLSLShadersToOneHeaderFile(fxc_compiler_path, - source_hlsl_file, - namespace, - shader_targets, - target_header_file, - target_cc_file): - """Compiles specified shaders from an .hlsl file into a single C++ header.""" - header_output = [] - # Invoke the compiler one at a time to write the c++ header file, - # then read that header file into |header_output|. - for (compiler_profile, hlsl_function_name) in shader_targets: - file_name_only = os.path.basename(source_hlsl_file) - base_filename, _ = os.path.splitext(file_name_only) - cpp_global_var_name = GetCppVariableName(hlsl_function_name) - - command = [fxc_compiler_path, - source_hlsl_file, # From this HLSL file - '/E', hlsl_function_name, # Compile one function - '/T', compiler_profile, # As a vertex or pixel shader - '/Vn', cpp_global_var_name, # Into a C++ constant thus named - '/Fh', target_header_file, # Declared in this C++ header file. - '/O3'] # Fast is better than slow. - child = subprocess.Popen(command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=False) - (out, err) = child.communicate() - if err or child.returncode: - print 'Error (%d) while compiling %s in file %s' % ( - child.returncode, hlsl_function_name, source_hlsl_file) - print err - sys.exit(1) - with open(target_header_file, 'r') as header: - header_output.append(header.read()) - - # Now, re-write the .h and .cc files with the concatenation of all - # the individual passes. - classname = '%sHLSL' % (ConvertToCamelCase(base_filename)) - preamble = '\n'.join([ - '/' * 77, - '// This file is auto-generated from %s' % file_name_only, - '//', - "// To edit it directly would be a fool's errand.", - '/' * 77, - '', - '']) - with open(target_header_file, 'wb') as h: - h.write(preamble) - h.write('#pragma once\n') - h.write('#include <windows.h>\n\n') - if namespace: - h.write('namespace %s {\n\n' % namespace) - h.write('namespace %s {\n\n' % classname) - for _, function_name in shader_targets: - h.write('extern const BYTE %s[];\n' % GetCppVariableName(function_name)) - h.write('\n} // namespace %s\n' % classname) - if namespace: - h.write('\n} // namespace %s\n' % namespace) - - with open(target_cc_file, 'wb') as cc: - cc.write(preamble) - cc.write('#include "%s"\n\n' % os.path.basename(target_header_file)) - if namespace: - cc.write('namespace %s {\n\n' % namespace) - cc.write('namespace %s {\n\n' % classname) - cc.write(''.join(header_output)) - cc.write('\n} // namespace %s\n' % classname) - if namespace: - cc.write('\n} // namespace %s\n' % namespace) - - -if __name__ == '__main__': - parser = optparse.OptionParser() - parser.add_option('--shader_compiler_tool', dest='compiler') - parser.add_option('--output_h_file', dest='header_file') - parser.add_option('--output_cc_file', dest='cc_file') - parser.add_option('--input_hlsl_file', dest='hlsl_file') - (options, args) = parser.parse_args() - - hlsl_file = os.path.abspath(options.hlsl_file) - shader_targets, namespace = ExtractShaderTargetNamesFromSource(hlsl_file) - - header_file = os.path.normpath(options.header_file) - cc_file = os.path.normpath(options.cc_file) - CompileMultipleHLSLShadersToOneHeaderFile(options.compiler, - hlsl_file, - namespace, - shader_targets, - header_file, - cc_file) diff --git a/ui/surface/d3d9_utils_win.cc b/ui/surface/d3d9_utils_win.cc deleted file mode 100644 index da82b2f..0000000 --- a/ui/surface/d3d9_utils_win.cc +++ /dev/null @@ -1,168 +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/surface/d3d9_utils_win.h" - -#include "base/debug/trace_event.h" -#include "base/files/file_path.h" -#include "base/scoped_native_library.h" -#include "base/win/scoped_comptr.h" -#include "ui/gfx/size.h" - -namespace { - -const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; -const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; -typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version, - IDirect3D9Ex **d3d); -} // namespace - -namespace ui_surface_d3d9_utils { - -bool LoadD3D9(base::ScopedNativeLibrary* storage) { - storage->Reset( - base::LoadNativeLibrary(base::FilePath(kD3D9ModuleName), NULL)); - return storage->is_valid(); -} - -bool CreateDevice(const base::ScopedNativeLibrary& d3d_module, - uint64 adapter_luid, - D3DDEVTYPE device_type, - uint32 presentation_interval, - IDirect3DDevice9Ex** device) { - Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( - d3d_module.GetFunctionPointer(kCreate3D9DeviceExName)); - if (!create_func) - return false; - - base::win::ScopedComPtr<IDirect3D9Ex> d3d; - HRESULT hr = create_func(D3D_SDK_VERSION, d3d.Receive()); - if (FAILED(hr)) - return false; - - UINT adapter = D3DADAPTER_DEFAULT; - - if (adapter_luid) { - UINT adapter_count = d3d->GetAdapterCount(); - for (adapter = 0; adapter < adapter_count; ++adapter) { - LUID luid; - HRESULT hr = d3d->GetAdapterLUID(adapter, &luid); - if (FAILED(hr)) - return false; - - if (memcmp(&luid, &adapter_luid, sizeof(adapter_luid)) == 0) - break; - } - - if (adapter == adapter_count) - return false; - } - - // Any old window will do to create the device. In practice the window to - // present to is an argument to IDirect3DDevice9::Present. - HWND window = GetDesktopWindow(); - - 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 = presentation_interval; - parameters.SwapEffect = D3DSWAPEFFECT_COPY; - - hr = d3d->CreateDeviceEx( - adapter, - device_type, - window, - D3DCREATE_FPU_PRESERVE | D3DCREATE_SOFTWARE_VERTEXPROCESSING | - D3DCREATE_DISABLE_PSGP_THREADING | D3DCREATE_MULTITHREADED, - ¶meters, - NULL, - device); - return SUCCEEDED(hr); -} - -bool OpenSharedTexture(IDirect3DDevice9* device, - int64 surface_handle, - const gfx::Size& size, - IDirect3DTexture9** opened_texture) { - TRACE_EVENT0("gpu", "OpenSharedTexture"); - HANDLE handle = reinterpret_cast<HANDLE>(surface_handle); - HRESULT hr = device->CreateTexture(size.width(), - size.height(), - 1, - D3DUSAGE_RENDERTARGET, - D3DFMT_A8R8G8B8, - D3DPOOL_DEFAULT, - opened_texture, - &handle); - return SUCCEEDED(hr); -} - -bool CreateOrReuseLockableSurface( - IDirect3DDevice9* device, - const gfx::Size& size, - base::win::ScopedComPtr<IDirect3DSurface9>* surface) { - if (!*surface || GetSize(*surface) != size) { - TRACE_EVENT0("gpu", "CreateRenderTarget"); - surface->Release(); - HRESULT hr = device->CreateRenderTarget( - size.width(), - size.height(), - D3DFMT_A8R8G8B8, - D3DMULTISAMPLE_NONE, - 0, - TRUE, - surface->Receive(), - NULL); - if (FAILED(hr)) - return false; - } - return true; -} - -bool CreateOrReuseRenderTargetTexture( - IDirect3DDevice9* device, - const gfx::Size& size, - base::win::ScopedComPtr<IDirect3DTexture9>* texture, - IDirect3DSurface9** render_target) { - if (!*texture || GetSize(*texture) != size) { - TRACE_EVENT0("gpu", "CreateTexture"); - texture->Release(); - HRESULT hr = device->CreateTexture( - size.width(), - size.height(), - 1, // Levels - D3DUSAGE_RENDERTARGET, - D3DFMT_A8R8G8B8, - D3DPOOL_DEFAULT, - texture->Receive(), - NULL); - if (!SUCCEEDED(hr)) - return false; - } - HRESULT hr = (*texture)->GetSurfaceLevel(0, render_target); - return SUCCEEDED(hr); -} - -gfx::Size GetSize(IDirect3DSurface9* surface) { - D3DSURFACE_DESC surface_description; - HRESULT hr = surface->GetDesc(&surface_description); - if (FAILED(hr)) - return gfx::Size(0, 0); - return gfx::Size(surface_description.Width, surface_description.Height); -} - -gfx::Size GetSize(IDirect3DTexture9* texture) { - D3DSURFACE_DESC surface_description; - HRESULT hr = texture->GetLevelDesc(0, &surface_description); - if (FAILED(hr)) - return gfx::Size(0, 0); - return gfx::Size(surface_description.Width, surface_description.Height); -} - -} // namespace ui_surface_d3d9_utils diff --git a/ui/surface/d3d9_utils_win.h b/ui/surface/d3d9_utils_win.h deleted file mode 100644 index 7934cb41..0000000 --- a/ui/surface/d3d9_utils_win.h +++ /dev/null @@ -1,87 +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. - -// Helper functions that Direct3D 9Ex code a little easier to work with for -// the ui/surface code. - -#ifndef UI_SURFACE_D3D9_UTILS_WIN_H_ -#define UI_SURFACE_D3D9_UTILS_WIN_H_ - -#include <d3d9.h> - -#include "base/basictypes.h" -#include "base/win/scoped_comptr.h" -#include "ui/surface/surface_export.h" - -namespace base { -class ScopedNativeLibrary; -} - -namespace gfx { -class Size; -} - -namespace ui_surface_d3d9_utils { - -// Visible for testing. Loads the Direct3D9 library. Returns true on success. -SURFACE_EXPORT -bool LoadD3D9(base::ScopedNativeLibrary* storage); - -// Visible for testing. Creates a Direct3D9 device suitable for use with the -// accelerated surface code. Returns true on success. -SURFACE_EXPORT -bool CreateDevice(const base::ScopedNativeLibrary& d3d_module, - uint64 adapter_luid, - D3DDEVTYPE device_type, - uint32 presentation_interval, - IDirect3DDevice9Ex** device); - -// Calls the Vista+ (WDDM1.0) variant of CreateTexture that semantically opens a -// texture allocated as shared. In this way textures allocated by another -// process can be used by a D3D context in this process. The shared texture is -// identified by its surface handle. The resulting texture is written into -// |opened_texture|. -// -// Returns true on success. -SURFACE_EXPORT -bool OpenSharedTexture(IDirect3DDevice9* device, - int64 surface_handle, - const gfx::Size& size, - IDirect3DTexture9** opened_texture); - -// Ensures that |surface| is a lockable surface of a specified |size|. If -// |*surface| is non-null and has dimensions that match |size|, it is reused. -// Otherwise, a new resource is created and the old one (if any) is freed. -// -// Returns true on success. -SURFACE_EXPORT -bool CreateOrReuseLockableSurface( - IDirect3DDevice9* device, - const gfx::Size& size, - base::win::ScopedComPtr<IDirect3DSurface9>* surface); - -// Ensures that |texture| is a render target texture of a specified |size|. If -// |*texture| is non-null and has dimensions that match |size|, it is reused. -// Otherwise, a new resource is created and the old one (if any) is freed. -// -// A reference to level 0 of the resulting texture is placed into -// |render_target|. -// -// Returns true on success. -SURFACE_EXPORT -bool CreateOrReuseRenderTargetTexture( - IDirect3DDevice9* device, - const gfx::Size& size, - base::win::ScopedComPtr<IDirect3DTexture9>* texture, - IDirect3DSurface9** render_target); - -SURFACE_EXPORT -gfx::Size GetSize(IDirect3DTexture9* texture); - -SURFACE_EXPORT -gfx::Size GetSize(IDirect3DSurface9* surface); - -} // namespace ui_surface_d3d9_utils - -#endif // UI_SURFACE_D3D9_UTILS_WIN_H_ diff --git a/ui/surface/surface.gyp b/ui/surface/surface.gyp index 868e599..f58f05d 100644 --- a/ui/surface/surface.gyp +++ b/ui/surface/surface.gyp @@ -14,41 +14,6 @@ '<(DEPTH)/third_party/khronos', ], }], - # TODO(ncarter): Does hlsl compilation belong in a shared location? - ['OS == "win"', { - 'include_dirs': [ - '<(INTERMEDIATE_DIR)/hlsl', - ], - 'rules': [ - { - 'variables': { - 'fxc': '<(windows_sdk_path)/bin/x86/fxc.exe', - 'h_file': '<(INTERMEDIATE_DIR)/hlsl/<(RULE_INPUT_ROOT)_hlsl_compiled.h', - 'cc_file': '<(INTERMEDIATE_DIR)/hlsl/<(RULE_INPUT_ROOT)_hlsl_compiled.cc', - }, - 'rule_name': 'compile_hlsl', - 'extension': 'hlsl', - 'inputs': [ - '<(fxc)', - 'compile_hlsl.py' - ], - 'outputs': [ - '<(h_file)', - '<(cc_file)', - ], - 'action': [ - 'python', - 'compile_hlsl.py', - '--shader_compiler_tool', '<(fxc)', - '--output_h_file', '<(h_file)', - '--output_cc_file', '<(cc_file)', - '--input_hlsl_file', '<(RULE_INPUT_PATH)', - ], - 'message': 'Generating shaders from <(RULE_INPUT_PATH)', - 'process_outputs_as_sources': 1, - }, - ], - }], ], }, 'targets': [ @@ -69,16 +34,7 @@ 'sources': [ 'accelerated_surface_mac.cc', 'accelerated_surface_mac.h', - 'accelerated_surface_transformer_win.cc', - 'accelerated_surface_transformer_win.h', - 'accelerated_surface_transformer_win.hlsl', - 'accelerated_surface_win.cc', - 'accelerated_surface_win.h', - 'd3d9_utils_win.cc', - 'd3d9_utils_win.h', 'surface_export.h', - 'surface_switches.h', - 'surface_switches.cc', 'transport_dib.h', 'transport_dib.cc', 'transport_dib_gtk.cc', @@ -90,29 +46,4 @@ ], }, ], - 'conditions': [ - ['OS == "win"', { - 'targets': [ - { - 'target_name': 'surface_gpu_tests', - 'type': '<(gtest_target_type)', - 'dependencies': [ - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/base.gyp:run_all_unittests', - '<(DEPTH)/media/media.gyp:media', - '<(DEPTH)/skia/skia.gyp:skia', - '<(DEPTH)/testing/gtest.gyp:gtest', - '<(DEPTH)/ui/events/events.gyp:events_base', - '<(DEPTH)/ui/gfx/gfx.gyp:gfx', - '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry', - '<(DEPTH)/ui/ui.gyp:ui', - 'surface', - ], - 'sources': [ - 'accelerated_surface_transformer_win_unittest.cc', - ], - }, - ], - }], - ], } diff --git a/ui/surface/surface_switches.cc b/ui/surface/surface_switches.cc deleted file mode 100644 index ab8b608..0000000 --- a/ui/surface/surface_switches.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2013 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/surface/surface_switches.h" - -namespace switches { - -// Flags for enabling speculative fix for http://crbug.com/169848 - -// Use GDI to do every first Present after the tab is unhidden. -const char kDoAllShowPresentWithGDI[] = "all-show-present-with-GDI"; - -// Use GDI to do the fist Present after the tab is unhidden. -const char kDoFirstShowPresentWithGDI[] = "first-show-present-with-GDI"; - - -} // namespace switches - diff --git a/ui/surface/surface_switches.h b/ui/surface/surface_switches.h deleted file mode 100644 index 13eabb5..0000000 --- a/ui/surface/surface_switches.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2013 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. - -#ifndef UI_SURFACE_SURFACE_SWITCHES_H_ -#define UI_SURFACE_SURFACE_SWITCHES_H_ - -#include "ui/surface/surface_export.h" - -// Defines all the command-line switches used by ui/surface. - -namespace switches { - -SURFACE_EXPORT extern const char kDoAllShowPresentWithGDI[]; -SURFACE_EXPORT extern const char kDoFirstShowPresentWithGDI[]; - -} // namespace switches - -#endif // UI_SURFACE_SURFACE_SWITCHES_H_ |