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

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: Test improvements. Created 7 years, 12 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::kVsOneTextureFlipY;
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 }
84 105
85 bool AcceleratedSurfaceTransformer::Init(IDirect3DDevice9* device) { 106 bool AcceleratedSurfaceTransformer::Init(IDirect3DDevice9* device) {
107 bool result = DoInit(device); // and DoInit() and DoInit well.
108 if (!result) {
109 ReleaseAll();
110 }
111 return result;
112 }
113
114 bool AcceleratedSurfaceTransformer::DoInit(IDirect3DDevice9* device) {
86 device_ = device; 115 device_ = device;
87 if (!InitShaderCombo( 116
88 ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsOneTexture, 117 {
89 ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsOneTexture, 118 D3DCAPS9 caps;
90 SIMPLE_TEXTURE)) { 119 HRESULT hr = device->GetDeviceCaps(&caps);
91 ReleaseAll(); 120 if (FAILED(hr))
121 return false;
122
123 device_supports_multiple_render_targets_ = (caps.NumSimultaneousRTs >= 2);
124
125 // Log statistics about which paths we take.
126 UMA_HISTOGRAM_BOOLEAN("GPU.AcceleratedSurfaceTransformerCanUseMRT",
127 device_supports_multiple_render_targets());
128 }
129
130 if (!InitShaderCombo(ONE_TEXTURE_FLIP_Y,
131 kVsOneTextureFlipY,
132 kPsOneTexture)) {
133 return false;
134 }
135
136 if (device_supports_multiple_render_targets()) {
137 if (!InitShaderCombo(RGB_TO_YV12_FAST__PASS_1_OF_2,
138 kVsFetch4Pixels,
139 kPsConvertRGBtoY8UV44)) {
140 return false;
141 }
142
143 if (!InitShaderCombo(RGB_TO_YV12_FAST__PASS_2_OF_2,
144 kVsFetch2Pixels,
145 kPsConvertUV44toU2V2)) {
146 return false;
147 }
148 }
149
miu 2012/12/27 21:40:17 It doesn't seem like the InitShaderCombo() calls f
ncarter (slow) 2013/01/07 22:49:10 The tests actually needed both paths to work, thou
150 if (!InitShaderCombo(RGB_TO_YV12_SLOW__PASS_1_OF_3,
151 kVsFetch4Pixels,
152 kPsConvertRGBtoY)) {
153 return false;
154 }
155
156 if (!InitShaderCombo(RGB_TO_YV12_SLOW__PASS_2_OF_3,
157 kVsFetch4PixelsScale2,
158 kPsConvertRGBtoU)) {
159 return false;
160 }
161
162 if (!InitShaderCombo(RGB_TO_YV12_SLOW__PASS_3_OF_3,
163 kVsFetch4PixelsScale2,
164 kPsConvertRGBtoV)) {
92 return false; 165 return false;
93 } 166 }
94 167
95 base::win::ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration; 168 base::win::ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration;
96 HRESULT hr = device_->CreateVertexDeclaration(g_vertexElements, 169 HRESULT hr = device_->CreateVertexDeclaration(g_vertexElements,
97 vertex_declaration.Receive()); 170 vertex_declaration.Receive());
98 if (!SUCCEEDED(hr)) { 171 if (FAILED(hr))
99 ReleaseAll();
100 return false; 172 return false;
101 } 173 hr = device_->SetVertexDeclaration(vertex_declaration);
102 device_->SetVertexDeclaration(vertex_declaration); 174 if (FAILED(hr))
175 return false;
103 176
104 return true; 177 return true;
105 } 178 }
106 179
107 bool AcceleratedSurfaceTransformer::InitShaderCombo( 180 bool AcceleratedSurfaceTransformer::InitShaderCombo(
181 ShaderCombo shader_combo_name,
108 const BYTE vertex_shader_instructions[], 182 const BYTE vertex_shader_instructions[],
109 const BYTE pixel_shader_instructions[], 183 const BYTE pixel_shader_instructions[]) {
110 ShaderCombo shader_combo_name) {
111 HRESULT hr = device_->CreateVertexShader( 184 HRESULT hr = device_->CreateVertexShader(
112 reinterpret_cast<const DWORD*>(vertex_shader_instructions), 185 reinterpret_cast<const DWORD*>(vertex_shader_instructions),
113 vertex_shaders_[shader_combo_name].Receive()); 186 vertex_shaders_[shader_combo_name].Receive());
114 187
115 if (FAILED(hr)) 188 if (FAILED(hr))
116 return false; 189 return false;
117 190
118 hr = device_->CreatePixelShader( 191 hr = device_->CreatePixelShader(
119 reinterpret_cast<const DWORD*>(pixel_shader_instructions), 192 reinterpret_cast<const DWORD*>(pixel_shader_instructions),
120 pixel_shaders_[shader_combo_name].Receive()); 193 pixel_shaders_[shader_combo_name].Receive());
(...skipping 15 matching lines...) Expand all
136 vertex_shaders_[i].Detach(); 209 vertex_shaders_[i].Detach();
137 } 210 }
138 device_.Detach(); 211 device_.Detach();
139 } 212 }
140 213
141 // Draw a textured quad to a surface. 214 // Draw a textured quad to a surface.
142 bool AcceleratedSurfaceTransformer::CopyInverted( 215 bool AcceleratedSurfaceTransformer::CopyInverted(
143 IDirect3DTexture9* src_texture, 216 IDirect3DTexture9* src_texture,
144 IDirect3DSurface9* dst_surface, 217 IDirect3DSurface9* dst_surface,
145 const gfx::Size& dst_size) { 218 const gfx::Size& dst_size) {
146 base::win::ScopedComPtr<IDirect3DSurface9> default_color_target;
147 device()->GetRenderTarget(0, default_color_target.Receive());
148 219
149 if (!SetShaderCombo(SIMPLE_TEXTURE)) 220 if (!SetShaderCombo(ONE_TEXTURE_FLIP_Y))
150 return false; 221 return false;
151 222
223 ScopedRenderTargetRestorer render_target_restorer(device(), 0);
152 device()->SetRenderTarget(0, dst_surface); 224 device()->SetRenderTarget(0, dst_surface);
153 device()->SetTexture(0, src_texture); 225 device()->SetTexture(0, src_texture);
226 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
apatrick_chromium 2013/01/07 22:56:53 These render states might affect something else us
ncarter (slow) 2013/01/07 23:24:52 AcceleratedSurface isn't doing any 3D rendering at
227 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
228 device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
229 device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
154 230
155 D3DVIEWPORT9 viewport = { 231 DrawScreenAlignedQuad(dst_size);
apatrick_chromium 2013/01/07 22:56:53 How did you get away without setting the viewport
ncarter (slow) 2013/01/07 23:24:52 http://msdn.microsoft.com/en-us/library/windows/de
156 0, 0,
157 dst_size.width(), dst_size.height(),
158 0, 1
159 };
160 device()->SetViewport(&viewport);
161 232
162 float halfPixelX = -1.0f / dst_size.width(); 233 // Clear surface references.
163 float halfPixelY = 1.0f / dst_size.height(); 234 device()->SetTexture(0, NULL);
235 return true;
236 }
237
238 void AcceleratedSurfaceTransformer::DrawScreenAlignedQuad(
239 const gfx::Size& size) {
240 const float target_size[] = { size.width(), size.height() };
241
242 // Set the uniform shader constant |kRenderTargetSize|, which is bound
243 // to register c0.
244 device()->SetVertexShaderConstantF(0, target_size, arraysize(target_size));
245
246 // We always send down the same vertices. The vertex program will take
247 // care of doing resolution-dependent position adjustment.
164 Vertex vertices[] = { 248 Vertex vertices[] = {
165 { halfPixelX - 1, halfPixelY + 1, 0.5f, 1, 0, 1 }, 249 { -1, +1, 0.5f, 1, 0, 0 },
166 { halfPixelX + 1, halfPixelY + 1, 0.5f, 1, 1, 1 }, 250 { +1, +1, 0.5f, 1, 1, 0 },
167 { halfPixelX + 1, halfPixelY - 1, 0.5f, 1, 1, 0 }, 251 { +1, -1, 0.5f, 1, 1, 1 },
168 { halfPixelX - 1, halfPixelY - 1, 0.5f, 1, 0, 0 } 252 { -1, -1, 0.5f, 1, 0, 1 }
169 }; 253 };
170 254
171 device()->BeginScene(); 255 device()->BeginScene();
172 device()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 256 device()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,
173 2, 257 2,
174 vertices, 258 vertices,
175 sizeof(vertices[0])); 259 sizeof(vertices[0]));
176 device()->EndScene(); 260 device()->EndScene();
177 261
178 // Clear surface references.
179 device()->SetRenderTarget(0, default_color_target);
180 device()->SetTexture(0, NULL);
181 return true;
182 } 262 }
183 263
184 // Resize an RGB surface using repeated linear interpolation. 264 // Resize an RGB surface using repeated linear interpolation.
185 bool AcceleratedSurfaceTransformer::ResizeBilinear( 265 bool AcceleratedSurfaceTransformer::ResizeBilinear(
186 IDirect3DSurface9* src_surface, 266 IDirect3DSurface9* src_surface,
187 const gfx::Rect& src_subrect, 267 const gfx::Rect& src_subrect,
188 IDirect3DSurface9* dst_surface) { 268 IDirect3DSurface9* dst_surface) {
189 gfx::Size src_size = GetSize(src_surface); 269 gfx::Size src_size = d3d_utils::GetSize(src_surface);
190 gfx::Size dst_size = GetSize(dst_surface); 270 gfx::Size dst_size = d3d_utils::GetSize(dst_surface);
191 271
192 if (src_size.IsEmpty() || dst_size.IsEmpty()) 272 if (src_size.IsEmpty() || dst_size.IsEmpty())
193 return false; 273 return false;
194 274
195 HRESULT hr = S_OK; 275 HRESULT hr = S_OK;
196 // Set up intermediate buffers needed for downsampling. 276 // Set up intermediate buffers needed for downsampling.
197 const int resample_count = 277 const int resample_count =
198 GetResampleCount(src_subrect, dst_size, src_size); 278 GetResampleCount(src_subrect, dst_size, src_size);
199 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2]; 279 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
200 const gfx::Size half_size = 280 const gfx::Size half_size =
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 if (FAILED(hr)) 319 if (FAILED(hr))
240 return false; 320 return false;
241 read_rect = write_rect; 321 read_rect = write_rect;
242 write_size = GetHalfSizeNoLessThan(write_size, dst_size); 322 write_size = GetHalfSizeNoLessThan(write_size, dst_size);
243 std::swap(read_buffer_index, write_buffer_index); 323 std::swap(read_buffer_index, write_buffer_index);
244 } 324 }
245 325
246 return true; 326 return true;
247 } 327 }
248 328
329 bool AcceleratedSurfaceTransformer::TransformRGBToYV12(
330 IDirect3DTexture9* src_surface,
331 const gfx::Size& dst_size,
332 IDirect3DSurface9** dst_y,
333 IDirect3DSurface9** dst_u,
334 IDirect3DSurface9** dst_v) {
335 gfx::Size packed_y_size;
336 gfx::Size packed_uv_size;
337 if (!AllocYUVBuffers(dst_size, &packed_y_size, &packed_uv_size,
338 dst_y, dst_u, dst_v)) {
339 return false;
340 }
341
342 if (device_supports_multiple_render_targets()) {
343 return TransformRGBToYV12_MRT(src_surface,
344 dst_size,
345 packed_y_size,
346 packed_uv_size,
347 *dst_y,
348 *dst_u,
349 *dst_v);
350 } else {
351 return TransformRGBToYV12_WithoutMRT(src_surface,
352 dst_size,
353 packed_y_size,
354 packed_uv_size,
355 *dst_y,
356 *dst_u,
357 *dst_v);
358 }
359 }
360
361 bool AcceleratedSurfaceTransformer::AllocYUVBuffers(
362 const gfx::Size& dst_size,
363 gfx::Size* y_size,
364 gfx::Size* uv_size,
365 IDirect3DSurface9** dst_y,
366 IDirect3DSurface9** dst_u,
367 IDirect3DSurface9** dst_v) {
368
369 // Y is full height, packed into 4 components.
370 *y_size = gfx::Size((dst_size.width() + 3) / 4, dst_size.height());
371
372 // U and V are half the size (rounded up) of Y.
373 *uv_size = gfx::Size((y_size->width() + 1) / 2, (y_size->height() + 1) / 2);
374
375 if (!d3d_utils::CreateTemporaryLockableSurface(device(), *y_size, dst_y))
376 return false;
377 if (!d3d_utils::CreateTemporaryLockableSurface(device(), *uv_size, dst_u))
378 return false;
379 if (!d3d_utils::CreateTemporaryLockableSurface(device(), *uv_size, dst_v))
380 return false;
381 return true;
382 }
383
384 bool AcceleratedSurfaceTransformer::TransformRGBToYV12_MRT(
385 IDirect3DTexture9* src_surface,
386 const gfx::Size& dst_size,
387 const gfx::Size& packed_y_size,
388 const gfx::Size& packed_uv_size,
389 IDirect3DSurface9* dst_y,
390 IDirect3DSurface9* dst_u,
391 IDirect3DSurface9* dst_v) {
392 TRACE_EVENT0("gpu", "RGBToYV12_MRT");
393
394 ScopedRenderTargetRestorer color0_restorer(device(), 0);
395 ScopedRenderTargetRestorer color1_restorer(device(), 1);
396
397 // Create an intermediate surface to hold the UUVV values. This is color
398 // target 1 for the first pass, and texture 0 for the second pass. Its
399 // values are not read afterwards.
400 base::win::ScopedComPtr<IDirect3DTexture9> uv_as_texture;
401 base::win::ScopedComPtr<IDirect3DSurface9> uv_as_surface;
402 if (!d3d_utils::CreateTemporaryRenderTargetTexture(device(),
403 packed_y_size,
404 uv_as_texture.Receive(),
405 uv_as_surface.Receive())) {
406 return false;
407 }
408
409 // Clamping is required if (dst_size.width() % 8 != 0) or if
410 // (dst_size.height != 0), so we set it always. Both passes rely on this.
411 device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
412 device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
413
414 /////////////////////////////////////////
415 // Pass 1: RGB --(scaled)--> YYYY + UUVV
416 SetShaderCombo(RGB_TO_YV12_FAST__PASS_1_OF_2);
417
418 // Enable bilinear filtering if scaling is required. The filtering will take
419 // place entirely in the first pass.
420 if (d3d_utils::GetSize(src_surface) != dst_size) {
421 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
422 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
423 } else {
424 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
425 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
426 }
427
428 device()->SetTexture(0, src_surface);
429 device()->SetRenderTarget(0, dst_y);
430 device()->SetRenderTarget(1, uv_as_surface);
431 DrawScreenAlignedQuad(dst_size);
432
433 /////////////////////////////////////////
434 // Pass 2: UUVV -> UUUU + VVVV
435 SetShaderCombo(RGB_TO_YV12_FAST__PASS_2_OF_2);
436
437 // The second pass uses bilinear minification to achieve vertical scaling,
438 // so enable it always.
439 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
440 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
441
442 device()->SetTexture(0, uv_as_texture);
443 device()->SetRenderTarget(0, dst_u);
444 device()->SetRenderTarget(1, dst_v);
445 DrawScreenAlignedQuad(packed_y_size);
446
447 // Clear surface references.
448 device()->SetTexture(0, NULL);
449 return true;
450 }
451
452 bool AcceleratedSurfaceTransformer::TransformRGBToYV12_WithoutMRT(
453 IDirect3DTexture9* src_surface,
454 const gfx::Size& dst_size,
455 const gfx::Size& packed_y_size,
456 const gfx::Size& packed_uv_size,
457 IDirect3DSurface9* dst_y,
458 IDirect3DSurface9* dst_u,
459 IDirect3DSurface9* dst_v) {
460 TRACE_EVENT0("gpu", "RGBToYV12_WithoutMRT");
461
462 ScopedRenderTargetRestorer color0_restorer(device(), 0);
463
464 base::win::ScopedComPtr<IDirect3DTexture9> scaled_src_surface;
465
466 // If scaling is requested, do it to a temporary texture. The MRT path
467 // gets a scale for free, so we need to support it here too (even though
468 // it's an extra operation).
469 if (d3d_utils::GetSize(src_surface) == dst_size) {
470 scaled_src_surface = src_surface;
471 } else {
472 base::win::ScopedComPtr<IDirect3DSurface9> src_level0;
473 HRESULT hr = src_surface->GetSurfaceLevel(0, src_level0.Receive());
474 if (FAILED(hr))
475 return false;
476
477 base::win::ScopedComPtr<IDirect3DSurface9> dst_level0;
478 if (!d3d_utils::CreateTemporaryRenderTargetTexture(
479 device(), dst_size,
480 scaled_src_surface.Receive(), dst_level0.Receive())) {
481 return false;
482 }
483
484 device()->StretchRect(src_level0, NULL, dst_level0, NULL, D3DTEXF_LINEAR);
apatrick_chromium 2013/01/07 22:56:53 Maybe this isn't an issue for your purposes but if
ncarter (slow) 2013/01/07 23:24:52 Yes, definitely; for the first phase I'm planning
485 }
486
487 // Input texture is the same for all three passes.
488 device()->SetTexture(0, scaled_src_surface);
489
490 // Clamping is required if (dst_size.width() % 8 != 0) or if
491 // (dst_size.height != 0), so we set it always. All passes rely on this.
492 device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
493 device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
494
495 /////////////////////
496 // Pass 1: RGB -> Y.
497 SetShaderCombo(RGB_TO_YV12_SLOW__PASS_1_OF_3);
498
499 // Pass 1 just needs point sampling.
500 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
501 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
502
503 device()->SetRenderTarget(0, dst_y);
504 DrawScreenAlignedQuad(dst_size);
505
506 // Passes 2 and 3 rely on bilinear minification to downsample U and V.
507 device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
508 device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
509
510 /////////////////////
511 // Pass 2: RGB -> U.
512 SetShaderCombo(RGB_TO_YV12_SLOW__PASS_2_OF_3);
513 device()->SetRenderTarget(0, dst_u);
514 DrawScreenAlignedQuad(dst_size);
515
516 /////////////////////
517 // Pass 3: RGB -> V.
518 SetShaderCombo(RGB_TO_YV12_SLOW__PASS_3_OF_3);
519 device()->SetRenderTarget(0, dst_v);
520 DrawScreenAlignedQuad(dst_size);
521
522 // Clear surface references.
523 device()->SetTexture(0, NULL);
524 return true;
525 }
526
249 IDirect3DDevice9* AcceleratedSurfaceTransformer::device() { 527 IDirect3DDevice9* AcceleratedSurfaceTransformer::device() {
250 return device_; 528 return device_;
251 } 529 }
252 530
531 bool AcceleratedSurfaceTransformer::device_supports_multiple_render_targets() {
miu 2012/12/27 21:40:17 nit: Consider inlining (allowed for simple accesso
ncarter (slow) 2013/01/07 22:49:10 Done.
532 return device_supports_multiple_render_targets_;
533 }
534
253 bool AcceleratedSurfaceTransformer::SetShaderCombo(ShaderCombo combo) { 535 bool AcceleratedSurfaceTransformer::SetShaderCombo(ShaderCombo combo) {
254 HRESULT hr = device()->SetVertexShader(vertex_shaders_[combo]); 536 HRESULT hr = device()->SetVertexShader(vertex_shaders_[combo]);
255 if (!SUCCEEDED(hr)) 537 if (!SUCCEEDED(hr))
256 return false; 538 return false;
257 hr = device()->SetPixelShader(pixel_shaders_[combo]); 539 hr = device()->SetPixelShader(pixel_shaders_[combo]);
258 if (!SUCCEEDED(hr)) 540 if (!SUCCEEDED(hr))
259 return false; 541 return false;
260 return true; 542 return true;
261 } 543 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698