Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(614)

Side by Side Diff: ui/surface/accelerated_surface_transformer_win.cc

Issue 11280318: YUV conversion on the GPU. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: "Yet more line endings." Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/surface/accelerated_surface_transformer_win.h" 5 #include "ui/surface/accelerated_surface_transformer_win.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "accelerated_surface_transformer_win_hlsl_compiled.h" 9 #include "accelerated_surface_transformer_win_hlsl_compiled.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
11 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
12 #include "base/metrics/histogram.h"
12 #include "base/single_thread_task_runner.h" 13 #include "base/single_thread_task_runner.h"
13 #include "base/synchronization/lock.h" 14 #include "base/synchronization/lock.h"
14 #include "base/synchronization/waitable_event.h" 15 #include "base/synchronization/waitable_event.h"
15 #include "base/win/scoped_comptr.h" 16 #include "base/win/scoped_comptr.h"
16 #include "ui/gfx/native_widget_types.h" 17 #include "ui/gfx/native_widget_types.h"
17 #include "ui/gfx/rect.h" 18 #include "ui/gfx/rect.h"
18 #include "ui/gfx/size.h" 19 #include "ui/gfx/size.h"
19 #include "ui/surface/d3d9_utils_win.h" 20 #include "ui/surface/d3d9_utils_win.h"
20 #include "ui/surface/surface_export.h" 21 #include "ui/surface/surface_export.h"
21 22
22 using base::win::ScopedComPtr; 23 using base::win::ScopedComPtr;
23 using std::vector; 24 using std::vector;
25 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertRGBtoY8UV44;
26 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertUV44toU2V2;
27 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsOneTexture;
28 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsFetch2Pixels;
29 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsFetch4Pixels;
30 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsOneTexture;
31 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsFetch4PixelsScale2;
32 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertRGBtoY;
33 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertRGBtoU;
34 using ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsConvertRGBtoV;
24 35
25 namespace d3d_utils = ui_surface_d3d9_utils; 36 namespace d3d_utils = ui_surface_d3d9_utils;
26 37
27 namespace { 38 namespace {
28 39
29 struct Vertex { 40 struct Vertex {
30 float x, y, z, w; 41 float x, y, z, w;
31 float u, v; 42 float u, v;
32 }; 43 };
33 44
34 const static D3DVERTEXELEMENT9 g_vertexElements[] = { 45 const static D3DVERTEXELEMENT9 g_vertexElements[] = {
35 { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0 }, 46 { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0 },
36 { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 }, 47 { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 },
37 D3DDECL_END() 48 D3DDECL_END()
38 }; 49 };
39 50
51 class ScopedRenderTargetRestorer {
52 public:
53 ScopedRenderTargetRestorer(IDirect3DDevice9* device,
54 int render_target_id)
55 : device_(device),
56 target_id_(render_target_id) {
57 device_->GetRenderTarget(target_id_, original_render_target_.Receive());
58 }
59 ~ScopedRenderTargetRestorer() {
60 device_->SetRenderTarget(target_id_, original_render_target_);
61 }
62 private:
63 ScopedComPtr<IDirect3DDevice9> device_;
64 int target_id_;
65 ScopedComPtr<IDirect3DSurface9> original_render_target_;
66 };
67
40 // Calculate the number necessary to transform |src_subrect| into |dst_size| 68 // Calculate the number necessary to transform |src_subrect| into |dst_size|
41 // by repeating downsampling of the image of |src_subrect| by a factor no more 69 // by repeating downsampling of the image of |src_subrect| by a factor no more
42 // than 2. 70 // than 2.
43 int GetResampleCount(const gfx::Rect& src_subrect, 71 int GetResampleCount(const gfx::Rect& src_subrect,
44 const gfx::Size& dst_size, 72 const gfx::Size& dst_size,
45 const gfx::Size& back_buffer_size) { 73 const gfx::Size& back_buffer_size) {
46 // At least one copy is required, since the back buffer itself is not 74 // At least one copy is required, since the back buffer itself is not
47 // lockable. 75 // lockable.
48 int min_resample_count = 1; 76 int min_resample_count = 1;
49 int width_count = 0; 77 int width_count = 0;
(...skipping 12 matching lines...) Expand all
62 min_resample_count); 90 min_resample_count);
63 } 91 }
64 92
65 // Returns half the size of |size| no smaller than |min_size|. 93 // Returns half the size of |size| no smaller than |min_size|.
66 gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size, 94 gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size,
67 const gfx::Size& min_size) { 95 const gfx::Size& min_size) {
68 return gfx::Size(std::max(min_size.width(), size.width() / 2), 96 return gfx::Size(std::max(min_size.width(), size.width() / 2),
69 std::max(min_size.height(), size.height() / 2)); 97 std::max(min_size.height(), size.height() / 2));
70 } 98 }
71 99
72 gfx::Size GetSize(IDirect3DSurface9* surface) {
73 D3DSURFACE_DESC surface_description;
74 HRESULT hr = surface->GetDesc(&surface_description);
75 if (FAILED(hr))
76 return gfx::Size(0, 0);
77 return gfx::Size(surface_description.Width, surface_description.Height);
78 }
79
80 } // namespace 100 } // namespace
81 101
82 102 AcceleratedSurfaceTransformer::AcceleratedSurfaceTransformer()
83 AcceleratedSurfaceTransformer::AcceleratedSurfaceTransformer() {} 103 : device_supports_multiple_render_targets_(false),
104 vertex_shader_sources_(),
105 pixel_shader_sources_() {
106
107 // Associate passes with actual shader programs.
108 vertex_shader_sources_[ONE_TEXTURE] = kVsOneTexture;
109 pixel_shader_sources_[ONE_TEXTURE] = kPsOneTexture;
110
111 vertex_shader_sources_[RGB_TO_YV12_FAST__PASS_1_OF_2] = kVsFetch4Pixels;
112 pixel_shader_sources_[RGB_TO_YV12_FAST__PASS_1_OF_2] = kPsConvertRGBtoY8UV44;
113
114 vertex_shader_sources_[RGB_TO_YV12_FAST__PASS_2_OF_2] = kVsFetch2Pixels;
115 pixel_shader_sources_[RGB_TO_YV12_FAST__PASS_2_OF_2] = kPsConvertUV44toU2V2;
116
117 vertex_shader_sources_[RGB_TO_YV12_SLOW__PASS_1_OF_3] = kVsFetch4Pixels;
118 pixel_shader_sources_[RGB_TO_YV12_SLOW__PASS_1_OF_3] = kPsConvertRGBtoY;
119
120 vertex_shader_sources_[RGB_TO_YV12_SLOW__PASS_2_OF_3] = kVsFetch4PixelsScale2;
121 pixel_shader_sources_[RGB_TO_YV12_SLOW__PASS_2_OF_3] = kPsConvertRGBtoU;
122
123 vertex_shader_sources_[RGB_TO_YV12_SLOW__PASS_3_OF_3] = kVsFetch4PixelsScale2;
124 pixel_shader_sources_[RGB_TO_YV12_SLOW__PASS_3_OF_3] = kPsConvertRGBtoV;
125
126 COMPILE_ASSERT(NUM_SHADERS == 6, must_initialize_shader_sources);
127 }
84 128
85 bool AcceleratedSurfaceTransformer::Init(IDirect3DDevice9* device) { 129 bool AcceleratedSurfaceTransformer::Init(IDirect3DDevice9* device) {
130 bool result = DoInit(device);
131 if (!result) {
132 ReleaseAll();
133 }
134 return result;
135 }
136
137 bool AcceleratedSurfaceTransformer::DoInit(IDirect3DDevice9* device) {
86 device_ = device; 138 device_ = device;
87 if (!InitShaderCombo( 139
88 ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsOneTexture, 140 {
89 ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsOneTexture, 141 D3DCAPS9 caps;
90 SIMPLE_TEXTURE)) { 142 HRESULT hr = device->GetDeviceCaps(&caps);
91 ReleaseAll(); 143 if (FAILED(hr))
92 return false; 144 return false;
93 } 145
146 device_supports_multiple_render_targets_ = (caps.NumSimultaneousRTs >= 2);
147
148 // Log statistics about which paths we take.
149 UMA_HISTOGRAM_BOOLEAN("GPU.AcceleratedSurfaceTransformerCanUseMRT",
150 device_supports_multiple_render_targets());
151 }
152
153 // Force compilation of all shaders that could be used on this GPU.
154 if (!CompileShaderCombo(ONE_TEXTURE))
155 return false;
156
157 if (device_supports_multiple_render_targets()) {
158 if (!CompileShaderCombo(RGB_TO_YV12_FAST__PASS_1_OF_2) ||
159 !CompileShaderCombo(RGB_TO_YV12_FAST__PASS_2_OF_2)) {
160 return false;
161 }
162 } else {
163 if (!CompileShaderCombo(RGB_TO_YV12_SLOW__PASS_1_OF_3) ||
164 !CompileShaderCombo(RGB_TO_YV12_SLOW__PASS_2_OF_3) ||
165 !CompileShaderCombo(RGB_TO_YV12_SLOW__PASS_3_OF_3)) {
166 return false;
167 }
168 }
169 COMPILE_ASSERT(NUM_SHADERS == 6, must_compile_at_doinit);
94 170
95 base::win::ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration; 171 base::win::ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration;
96 HRESULT hr = device_->CreateVertexDeclaration(g_vertexElements, 172 HRESULT hr = device_->CreateVertexDeclaration(g_vertexElements,
97 vertex_declaration.Receive()); 173 vertex_declaration.Receive());
98 if (!SUCCEEDED(hr)) {
99 ReleaseAll();
100 return false;
101 }
102 device_->SetVertexDeclaration(vertex_declaration);
103
104 return true;
105 }
106
107 bool AcceleratedSurfaceTransformer::InitShaderCombo(
108 const BYTE vertex_shader_instructions[],
109 const BYTE pixel_shader_instructions[],
110 ShaderCombo shader_combo_name) {
111 HRESULT hr = device_->CreateVertexShader(
112 reinterpret_cast<const DWORD*>(vertex_shader_instructions),
113 vertex_shaders_[shader_combo_name].Receive());
114
115 if (FAILED(hr)) 174 if (FAILED(hr))
116 return false; 175 return false;
117 176 hr = device_->SetVertexDeclaration(vertex_declaration);
118 hr = device_->CreatePixelShader( 177 if (FAILED(hr))
119 reinterpret_cast<const DWORD*>(pixel_shader_instructions), 178 return false;
120 pixel_shaders_[shader_combo_name].Receive()); 179
121 180 return true;
122 return SUCCEEDED(hr); 181 }
123 } 182
124 183 bool AcceleratedSurfaceTransformer::CompileShaderCombo(
184 ShaderCombo shader) {
185 if (!vertex_shaders_[shader]) {
186 HRESULT hr = device_->CreateVertexShader(
187 reinterpret_cast<const DWORD*>(vertex_shader_sources_[shader]),
188 vertex_shaders_[shader].Receive());
189
190 if (FAILED(hr))
191 return false;
192
193 for (int i = 0; i < NUM_SHADERS; ++i) {
194 if (vertex_shader_sources_[i] == vertex_shader_sources_[shader] &&
195 i != shader) {
196 vertex_shaders_[i] = vertex_shaders_[shader];
197 }
198 }
199 }
200
201 if (!pixel_shaders_[shader]) {
202 HRESULT hr = device_->CreatePixelShader(
203 reinterpret_cast<const DWORD*>(pixel_shader_sources_[shader]),
204 pixel_shaders_[shader].Receive());
205
206 if (FAILED(hr))
207 return false;
208
209 for (int i = 0; i < NUM_SHADERS; ++i) {
210 if (pixel_shader_sources_[i] == pixel_shader_sources_[shader] &&
211 i != shader) {
212 pixel_shaders_[i] = pixel_shaders_[shader];
213 }
214 }
215 }
216
217 return true;
218 }
125 219
126 void AcceleratedSurfaceTransformer::ReleaseAll() { 220 void AcceleratedSurfaceTransformer::ReleaseAll() {
127 for (int i = 0; i < NUM_SHADERS; i++) { 221 for (int i = 0; i < NUM_SHADERS; i++) {
128 vertex_shaders_[i] = NULL; 222 vertex_shaders_[i] = NULL;
129 vertex_shaders_[i] = NULL; 223 vertex_shaders_[i] = NULL;
130 } 224 }
131 device_ = NULL; 225 device_ = NULL;
132 } 226 }
133 void AcceleratedSurfaceTransformer::DetachAll() { 227 void AcceleratedSurfaceTransformer::DetachAll() {
134 for (int i = 0; i < NUM_SHADERS; i++) { 228 for (int i = 0; i < NUM_SHADERS; i++) {
135 vertex_shaders_[i].Detach(); 229 vertex_shaders_[i].Detach();
136 vertex_shaders_[i].Detach(); 230 vertex_shaders_[i].Detach();
137 } 231 }
138 device_.Detach(); 232 device_.Detach();
139 } 233 }
140 234
141 // Draw a textured quad to a surface.
142 bool AcceleratedSurfaceTransformer::CopyInverted( 235 bool AcceleratedSurfaceTransformer::CopyInverted(
143 IDirect3DTexture9* src_texture, 236 IDirect3DTexture9* src_texture,
144 IDirect3DSurface9* dst_surface, 237 IDirect3DSurface9* dst_surface,
145 const gfx::Size& dst_size) { 238 const gfx::Size& dst_size) {
146 base::win::ScopedComPtr<IDirect3DSurface9> default_color_target; 239 return CopyWithTextureScale(src_texture, dst_surface, dst_size, 1.0f, -1.0f);
147 device()->GetRenderTarget(0, default_color_target.Receive()); 240 }
148 241
149 if (!SetShaderCombo(SIMPLE_TEXTURE)) 242 bool AcceleratedSurfaceTransformer::Copy(
150 return false; 243 IDirect3DTexture9* src_texture,
151 244 IDirect3DSurface9* dst_surface,
245 const gfx::Size& dst_size) {
246 return CopyWithTextureScale(src_texture, dst_surface, dst_size, 1.0f, 1.0f);
247 }
248
249 bool AcceleratedSurfaceTransformer::CopyWithTextureScale(
250 IDirect3DTexture9* src_texture,
251 IDirect3DSurface9* dst_surface,
252 const gfx::Size& dst_size,
253 float texture_scale_x,
254 float texture_scale_y) {
255
256 if (!SetShaderCombo(ONE_TEXTURE))
257 return false;
258
259 // Set the kTextureScale vertex shader constant, which is assigned to
260 // register 1.
261 float texture_scale[4] = {texture_scale_x, texture_scale_y, 0, 0};
262 device()->SetVertexShaderConstantF(1, texture_scale, 1);
263
264 ScopedRenderTargetRestorer render_target_restorer(device(), 0);
152 device()->SetRenderTarget(0, dst_surface); 265 device()->SetRenderTarget(0, dst_surface);
153 device()->SetTexture(0, src_texture); 266 device()->SetTexture(0, src_texture);
154 267
155 D3DVIEWPORT9 viewport = { 268 D3DVIEWPORT9 viewport = {
156 0, 0, 269 0, 0,
157 dst_size.width(), dst_size.height(), 270 dst_size.width(), dst_size.height(),
158 0, 1 271 0, 1
159 }; 272 };
160 device()->SetViewport(&viewport); 273 device()->SetViewport(&viewport);
161 274
162 float halfPixelX = -1.0f / dst_size.width(); 275 if (d3d_utils::GetSize(src_texture) == dst_size) {
163 float halfPixelY = 1.0f / dst_size.height(); 276 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
277 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
278 } else {
279 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
280 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
281 }
282 device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
283 device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
284
285 DrawScreenAlignedQuad(dst_size);
286
287 // Clear surface references.
288 device()->SetTexture(0, NULL);
289 return true;
290 }
291
292 void AcceleratedSurfaceTransformer::DrawScreenAlignedQuad(
293 const gfx::Size& size) {
294 const float target_size[4] = { size.width(), size.height(), 0, 0};
295
296 // Set the uniform shader constant |kRenderTargetSize|, which is bound
297 // to register c0.
298 device()->SetVertexShaderConstantF(0, target_size, 1);
299
300 // We always send down the same vertices. The vertex program will take
301 // care of doing resolution-dependent position adjustment.
164 Vertex vertices[] = { 302 Vertex vertices[] = {
165 { halfPixelX - 1, halfPixelY + 1, 0.5f, 1, 0, 1 }, 303 { -1, +1, 0.5f, 1, 0, 0 },
166 { halfPixelX + 1, halfPixelY + 1, 0.5f, 1, 1, 1 }, 304 { +1, +1, 0.5f, 1, 1, 0 },
167 { halfPixelX + 1, halfPixelY - 1, 0.5f, 1, 1, 0 }, 305 { +1, -1, 0.5f, 1, 1, 1 },
168 { halfPixelX - 1, halfPixelY - 1, 0.5f, 1, 0, 0 } 306 { -1, -1, 0.5f, 1, 0, 1 }
169 }; 307 };
170 308
171 device()->BeginScene(); 309 device()->BeginScene();
172 device()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 310 device()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,
173 2, 311 2,
174 vertices, 312 vertices,
175 sizeof(vertices[0])); 313 sizeof(vertices[0]));
176 device()->EndScene(); 314 device()->EndScene();
177 315
178 // Clear surface references.
179 device()->SetRenderTarget(0, default_color_target);
180 device()->SetTexture(0, NULL);
181 return true;
182 } 316 }
183 317
184 // Resize an RGB surface using repeated linear interpolation. 318 // Resize an RGB surface using repeated linear interpolation.
185 bool AcceleratedSurfaceTransformer::ResizeBilinear( 319 bool AcceleratedSurfaceTransformer::ResizeBilinear(
186 IDirect3DSurface9* src_surface, 320 IDirect3DSurface9* src_surface,
187 const gfx::Rect& src_subrect, 321 const gfx::Rect& src_subrect,
188 IDirect3DSurface9* dst_surface) { 322 IDirect3DSurface9* dst_surface) {
189 gfx::Size src_size = GetSize(src_surface); 323 gfx::Size src_size = d3d_utils::GetSize(src_surface);
190 gfx::Size dst_size = GetSize(dst_surface); 324 gfx::Size dst_size = d3d_utils::GetSize(dst_surface);
191 325
192 if (src_size.IsEmpty() || dst_size.IsEmpty()) 326 if (src_size.IsEmpty() || dst_size.IsEmpty())
193 return false; 327 return false;
194 328
195 HRESULT hr = S_OK; 329 HRESULT hr = S_OK;
196 // Set up intermediate buffers needed for downsampling. 330 // Set up intermediate buffers needed for downsampling.
197 const int resample_count = 331 const int resample_count =
198 GetResampleCount(src_subrect, dst_size, src_size); 332 GetResampleCount(src_subrect, dst_size, src_size);
199 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2]; 333 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
200 const gfx::Size half_size = 334 const gfx::Size half_size =
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 if (FAILED(hr)) 373 if (FAILED(hr))
240 return false; 374 return false;
241 read_rect = write_rect; 375 read_rect = write_rect;
242 write_size = GetHalfSizeNoLessThan(write_size, dst_size); 376 write_size = GetHalfSizeNoLessThan(write_size, dst_size);
243 std::swap(read_buffer_index, write_buffer_index); 377 std::swap(read_buffer_index, write_buffer_index);
244 } 378 }
245 379
246 return true; 380 return true;
247 } 381 }
248 382
383 bool AcceleratedSurfaceTransformer::TransformRGBToYV12(
384 IDirect3DTexture9* src_surface,
385 const gfx::Size& dst_size,
386 IDirect3DSurface9** dst_y,
387 IDirect3DSurface9** dst_u,
388 IDirect3DSurface9** dst_v) {
389 gfx::Size packed_y_size;
390 gfx::Size packed_uv_size;
391 if (!AllocYUVBuffers(dst_size, &packed_y_size, &packed_uv_size,
392 dst_y, dst_u, dst_v)) {
393 return false;
394 }
395
396 if (device_supports_multiple_render_targets()) {
397 return TransformRGBToYV12_MRT(src_surface,
398 dst_size,
399 packed_y_size,
400 packed_uv_size,
401 *dst_y,
402 *dst_u,
403 *dst_v);
404 } else {
405 return TransformRGBToYV12_WithoutMRT(src_surface,
406 dst_size,
407 packed_y_size,
408 packed_uv_size,
409 *dst_y,
410 *dst_u,
411 *dst_v);
412 }
413 }
414
415 bool AcceleratedSurfaceTransformer::AllocYUVBuffers(
416 const gfx::Size& dst_size,
417 gfx::Size* y_size,
418 gfx::Size* uv_size,
419 IDirect3DSurface9** dst_y,
420 IDirect3DSurface9** dst_u,
421 IDirect3DSurface9** dst_v) {
422
423 // Y is full height, packed into 4 components.
424 *y_size = gfx::Size((dst_size.width() + 3) / 4, dst_size.height());
425
426 // U and V are half the size (rounded up) of Y.
427 *uv_size = gfx::Size((y_size->width() + 1) / 2, (y_size->height() + 1) / 2);
428
429 if (!d3d_utils::CreateTemporaryLockableSurface(device(), *y_size, dst_y))
430 return false;
431 if (!d3d_utils::CreateTemporaryLockableSurface(device(), *uv_size, dst_u))
432 return false;
433 if (!d3d_utils::CreateTemporaryLockableSurface(device(), *uv_size, dst_v))
434 return false;
435 return true;
436 }
437
438 bool AcceleratedSurfaceTransformer::TransformRGBToYV12_MRT(
439 IDirect3DTexture9* src_surface,
440 const gfx::Size& dst_size,
441 const gfx::Size& packed_y_size,
442 const gfx::Size& packed_uv_size,
443 IDirect3DSurface9* dst_y,
444 IDirect3DSurface9* dst_u,
445 IDirect3DSurface9* dst_v) {
446 TRACE_EVENT0("gpu", "RGBToYV12_MRT");
447
448 ScopedRenderTargetRestorer color0_restorer(device(), 0);
449 ScopedRenderTargetRestorer color1_restorer(device(), 1);
450
451 // Create an intermediate surface to hold the UUVV values. This is color
452 // target 1 for the first pass, and texture 0 for the second pass. Its
453 // values are not read afterwards.
454 base::win::ScopedComPtr<IDirect3DTexture9> uv_as_texture;
455 base::win::ScopedComPtr<IDirect3DSurface9> uv_as_surface;
456 if (!d3d_utils::CreateTemporaryRenderTargetTexture(device(),
457 packed_y_size,
458 uv_as_texture.Receive(),
459 uv_as_surface.Receive())) {
460 return false;
461 }
462
463 // Clamping is required if (dst_size.width() % 8 != 0) or if
464 // (dst_size.height != 0), so we set it always. Both passes rely on this.
465 device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
466 device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
467
468 /////////////////////////////////////////
469 // Pass 1: RGB --(scaled)--> YYYY + UUVV
470 SetShaderCombo(RGB_TO_YV12_FAST__PASS_1_OF_2);
471
472 // Enable bilinear filtering if scaling is required. The filtering will take
473 // place entirely in the first pass.
474 if (d3d_utils::GetSize(src_surface) != dst_size) {
475 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
476 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
477 } else {
478 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
479 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
480 }
481
482 device()->SetTexture(0, src_surface);
483 device()->SetRenderTarget(0, dst_y);
484 device()->SetRenderTarget(1, uv_as_surface);
485 DrawScreenAlignedQuad(dst_size);
486
487 /////////////////////////////////////////
488 // Pass 2: UUVV -> UUUU + VVVV
489 SetShaderCombo(RGB_TO_YV12_FAST__PASS_2_OF_2);
490
491 // The second pass uses bilinear minification to achieve vertical scaling,
492 // so enable it always.
493 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
494 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
495
496 device()->SetTexture(0, uv_as_texture);
497 device()->SetRenderTarget(0, dst_u);
498 device()->SetRenderTarget(1, dst_v);
499 DrawScreenAlignedQuad(packed_y_size);
500
501 // Clear surface references.
502 device()->SetTexture(0, NULL);
503 return true;
504 }
505
506 bool AcceleratedSurfaceTransformer::TransformRGBToYV12_WithoutMRT(
507 IDirect3DTexture9* src_surface,
508 const gfx::Size& dst_size,
509 const gfx::Size& packed_y_size,
510 const gfx::Size& packed_uv_size,
511 IDirect3DSurface9* dst_y,
512 IDirect3DSurface9* dst_u,
513 IDirect3DSurface9* dst_v) {
514 TRACE_EVENT0("gpu", "RGBToYV12_WithoutMRT");
515
516 ScopedRenderTargetRestorer color0_restorer(device(), 0);
517
518 base::win::ScopedComPtr<IDirect3DTexture9> scaled_src_surface;
519
520 // If scaling is requested, do it to a temporary texture. The MRT path
521 // gets a scale for free, so we need to support it here too (even though
522 // it's an extra operation).
523 if (d3d_utils::GetSize(src_surface) == dst_size) {
524 scaled_src_surface = src_surface;
525 } else {
526 base::win::ScopedComPtr<IDirect3DSurface9> dst_level0;
527 if (!d3d_utils::CreateTemporaryRenderTargetTexture(
528 device(), dst_size,
529 scaled_src_surface.Receive(), dst_level0.Receive())) {
530 return false;
531 }
532
533 if (!Copy(src_surface, dst_level0, dst_size)) {
534 return false;
535 }
536 }
537
538 // Input texture is the same for all three passes.
539 device()->SetTexture(0, scaled_src_surface);
540
541 // Clamping is required if (dst_size.width() % 8 != 0) or if
542 // (dst_size.height != 0), so we set it always. All passes rely on this.
543 device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
544 device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
545
546 /////////////////////
547 // Pass 1: RGB -> Y.
548 SetShaderCombo(RGB_TO_YV12_SLOW__PASS_1_OF_3);
549
550 // Pass 1 just needs point sampling.
551 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
552 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
553
554 device()->SetRenderTarget(0, dst_y);
555 DrawScreenAlignedQuad(dst_size);
556
557 // Passes 2 and 3 rely on bilinear minification to downsample U and V.
558 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
559 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
560
561 /////////////////////
562 // Pass 2: RGB -> U.
563 SetShaderCombo(RGB_TO_YV12_SLOW__PASS_2_OF_3);
564 device()->SetRenderTarget(0, dst_u);
565 DrawScreenAlignedQuad(dst_size);
566
567 /////////////////////
568 // Pass 3: RGB -> V.
569 SetShaderCombo(RGB_TO_YV12_SLOW__PASS_3_OF_3);
570 device()->SetRenderTarget(0, dst_v);
571 DrawScreenAlignedQuad(dst_size);
572
573 // Clear surface references.
574 device()->SetTexture(0, NULL);
575 return true;
576 }
577
249 IDirect3DDevice9* AcceleratedSurfaceTransformer::device() { 578 IDirect3DDevice9* AcceleratedSurfaceTransformer::device() {
250 return device_; 579 return device_;
251 } 580 }
252 581
253 bool AcceleratedSurfaceTransformer::SetShaderCombo(ShaderCombo combo) { 582 bool AcceleratedSurfaceTransformer::SetShaderCombo(ShaderCombo combo) {
583 // Compile shaders on first use, if needed. Normally the compilation should
584 // already have happened at Init() time, but test code might force
585 // us down an unusual path.
586 if (!CompileShaderCombo(combo))
587 return false;
588
254 HRESULT hr = device()->SetVertexShader(vertex_shaders_[combo]); 589 HRESULT hr = device()->SetVertexShader(vertex_shaders_[combo]);
255 if (!SUCCEEDED(hr)) 590 if (!SUCCEEDED(hr))
256 return false; 591 return false;
257 hr = device()->SetPixelShader(pixel_shaders_[combo]); 592 hr = device()->SetPixelShader(pixel_shaders_[combo]);
258 if (!SUCCEEDED(hr)) 593 if (!SUCCEEDED(hr))
259 return false; 594 return false;
260 return true; 595 return true;
261 } 596 }
OLDNEW
« no previous file with comments | « ui/surface/accelerated_surface_transformer_win.h ('k') | ui/surface/accelerated_surface_transformer_win.hlsl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698