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

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

Issue 11464017: Separate image processing logic from presentation logic. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed dependencies of surface_gpu_tests. 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ui/surface/accelerated_surface_transformer_win.h"
6
7 #include <vector>
8
9 #include "accelerated_surface_transformer_win_hlsl_compiled.h"
10 #include "base/debug/trace_event.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/synchronization/lock.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/win/scoped_comptr.h"
16 #include "ui/gfx/native_widget_types.h"
17 #include "ui/gfx/rect.h"
18 #include "ui/gfx/size.h"
19 #include "ui/surface/d3d9_utils_win.h"
20 #include "ui/surface/surface_export.h"
21
22 using base::win::ScopedComPtr;
23 using std::vector;
24
25 namespace d3d_utils = ui_surface_d3d9_utils;
26
27 namespace {
28
29 struct Vertex {
30 float x, y, z, w;
31 float u, v;
32 };
33
34 const static D3DVERTEXELEMENT9 g_vertexElements[] = {
35 { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0 },
36 { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 },
37 D3DDECL_END()
38 };
39
40 // 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
42 // than 2.
43 int GetResampleCount(const gfx::Rect& src_subrect,
44 const gfx::Size& dst_size,
45 const gfx::Size& back_buffer_size) {
46 // At least one copy is required, since the back buffer itself is not
47 // lockable.
48 int min_resample_count = 1;
49 int width_count = 0;
50 int width = src_subrect.width();
51 while (width > dst_size.width()) {
52 ++width_count;
53 width >>= 1;
54 }
55 int height_count = 0;
56 int height = src_subrect.height();
57 while (height > dst_size.height()) {
58 ++height_count;
59 height >>= 1;
60 }
61 return std::max(std::max(width_count, height_count),
62 min_resample_count);
63 }
64
65 // Returns half the size of |size| no smaller than |min_size|.
66 gfx::Size GetHalfSizeNoLessThan(const gfx::Size& size,
67 const gfx::Size& min_size) {
68 return gfx::Size(std::max(min_size.width(), size.width() / 2),
69 std::max(min_size.height(), size.height() / 2));
70 }
71
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
81
82
83 AcceleratedSurfaceTransformer::AcceleratedSurfaceTransformer() {}
84
85 bool AcceleratedSurfaceTransformer::Init(IDirect3DDevice9* device) {
86 device_ = device;
87 if (!InitShaderCombo(
88 ui_surface::AcceleratedSurfaceTransformerWinHLSL::kVsOneTexture,
89 ui_surface::AcceleratedSurfaceTransformerWinHLSL::kPsOneTexture,
90 SIMPLE_TEXTURE)) {
91 ReleaseAll();
92 return false;
93 }
94
95 base::win::ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration;
96 HRESULT hr = device_->CreateVertexDeclaration(g_vertexElements,
97 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))
116 return false;
117
118 hr = device_->CreatePixelShader(
119 reinterpret_cast<const DWORD*>(pixel_shader_instructions),
120 pixel_shaders_[shader_combo_name].Receive());
121
122 return SUCCEEDED(hr);
123 }
124
125
126 void AcceleratedSurfaceTransformer::ReleaseAll() {
127 for (int i = 0; i < NUM_SHADERS; i++) {
128 vertex_shaders_[i] = NULL;
129 vertex_shaders_[i] = NULL;
130 }
131 device_ = NULL;
132 }
133 void AcceleratedSurfaceTransformer::DetachAll() {
134 for (int i = 0; i < NUM_SHADERS; i++) {
135 vertex_shaders_[i].Detach();
136 vertex_shaders_[i].Detach();
137 }
138 device_.Detach();
139 }
140
141 // Draw a textured quad to a surface.
142 bool AcceleratedSurfaceTransformer::CopyInverted(
143 IDirect3DTexture9* src_texture,
144 IDirect3DSurface9* dst_surface,
145 const gfx::Size& dst_size) {
146 base::win::ScopedComPtr<IDirect3DSurface9> default_color_target;
147 device()->GetRenderTarget(0, default_color_target.Receive());
148
149 if (!SetShaderCombo(SIMPLE_TEXTURE))
150 return false;
151
152 device()->SetRenderTarget(0, dst_surface);
153 device()->SetTexture(0, src_texture);
154
155 D3DVIEWPORT9 viewport = {
156 0, 0,
157 dst_size.width(), dst_size.height(),
158 0, 1
159 };
160 device()->SetViewport(&viewport);
161
162 float halfPixelX = -1.0f / dst_size.width();
163 float halfPixelY = 1.0f / dst_size.height();
164 Vertex vertices[] = {
165 { halfPixelX - 1, halfPixelY + 1, 0.5f, 1, 0, 1 },
166 { halfPixelX + 1, halfPixelY + 1, 0.5f, 1, 1, 1 },
167 { halfPixelX + 1, halfPixelY - 1, 0.5f, 1, 1, 0 },
168 { halfPixelX - 1, halfPixelY - 1, 0.5f, 1, 0, 0 }
169 };
170
171 device()->BeginScene();
172 device()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,
173 2,
174 vertices,
175 sizeof(vertices[0]));
176 device()->EndScene();
177
178 // Clear surface references.
179 device()->SetRenderTarget(0, default_color_target);
180 device()->SetTexture(0, NULL);
181 return true;
182 }
183
184 // Resize an RGB surface using repeated linear interpolation.
185 bool AcceleratedSurfaceTransformer::ResizeBilinear(
186 IDirect3DSurface9* src_surface,
187 const gfx::Rect& src_subrect,
188 IDirect3DSurface9* dst_surface) {
189 gfx::Size src_size = GetSize(src_surface);
190 gfx::Size dst_size = GetSize(dst_surface);
191
192 if (src_size.IsEmpty() || dst_size.IsEmpty())
193 return false;
194
195 HRESULT hr = S_OK;
196 // Set up intermediate buffers needed for downsampling.
197 const int resample_count =
198 GetResampleCount(src_subrect, dst_size, src_size);
199 base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
200 const gfx::Size half_size =
201 GetHalfSizeNoLessThan(src_subrect.size(), dst_size);
202 if (resample_count > 1) {
203 TRACE_EVENT0("gpu", "CreateTemporarySurface");
204 if (!d3d_utils::CreateTemporaryLockableSurface(device(),
205 half_size,
206 temp_buffer[0].Receive()))
207 return false;
208 }
209 if (resample_count > 2) {
210 TRACE_EVENT0("gpu", "CreateTemporarySurface");
211 const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, dst_size);
212 if (!d3d_utils::CreateTemporaryLockableSurface(device(),
213 quarter_size,
214 temp_buffer[1].Receive()))
215 return false;
216 }
217
218 // Repeat downsampling the surface until its size becomes identical to
219 // |dst_size|. We keep the factor of each downsampling no more than two
220 // because using a factor more than two can introduce aliasing.
221 RECT read_rect = src_subrect.ToRECT();
222 gfx::Size write_size = half_size;
223 int read_buffer_index = 1;
224 int write_buffer_index = 0;
225 for (int i = 0; i < resample_count; ++i) {
226 TRACE_EVENT0("gpu", "StretchRect");
227 IDirect3DSurface9* read_buffer =
228 (i == 0) ? src_surface : temp_buffer[read_buffer_index];
229 IDirect3DSurface9* write_buffer =
230 (i == resample_count - 1) ? dst_surface :
231 temp_buffer[write_buffer_index];
232 RECT write_rect = gfx::Rect(write_size).ToRECT();
233 hr = device()->StretchRect(read_buffer,
234 &read_rect,
235 write_buffer,
236 &write_rect,
237 D3DTEXF_LINEAR);
238
239 if (FAILED(hr))
240 return false;
241 read_rect = write_rect;
242 write_size = GetHalfSizeNoLessThan(write_size, dst_size);
243 std::swap(read_buffer_index, write_buffer_index);
244 }
245
246 return true;
247 }
248
249 IDirect3DDevice9* AcceleratedSurfaceTransformer::device() {
250 return device_;
251 }
252
253 bool AcceleratedSurfaceTransformer::SetShaderCombo(ShaderCombo combo) {
254 HRESULT hr = device()->SetVertexShader(vertex_shaders_[combo]);
255 if (!SUCCEEDED(hr))
256 return false;
257 hr = device()->SetPixelShader(pixel_shaders_[combo]);
258 if (!SUCCEEDED(hr))
259 return false;
260 return true;
261 }
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