| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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/gfx/compositor/compositor.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <d3dx10.h> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/compiler_specific.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/stl_util.h" | |
| 14 #include "base/string_piece.h" | |
| 15 #include "base/win/scoped_comptr.h" | |
| 16 #include "grit/gfx_resources.h" | |
| 17 #include "third_party/skia/include/core/SkCanvas.h" | |
| 18 #include "ui/base/resource/resource_bundle.h" | |
| 19 #include "ui/gfx/canvas_skia.h" | |
| 20 #include "ui/gfx/rect.h" | |
| 21 #include "ui/gfx/transform.h" | |
| 22 | |
| 23 // TODO(sky): this is a hack, figure out real error handling. | |
| 24 #define RETURN_IF_FAILED(error) \ | |
| 25 if (error != S_OK) { \ | |
| 26 this->Errored(error); \ | |
| 27 VLOG(1) << "D3D failed" << error; \ | |
| 28 return; \ | |
| 29 } | |
| 30 | |
| 31 using base::win::ScopedComPtr; | |
| 32 | |
| 33 namespace ui { | |
| 34 | |
| 35 namespace { | |
| 36 | |
| 37 class CompositorWin; | |
| 38 | |
| 39 // Vertex structure used by the compositor. | |
| 40 struct Vertex { | |
| 41 D3DXVECTOR3 position; | |
| 42 D3DXVECTOR2 texture_offset; | |
| 43 }; | |
| 44 | |
| 45 // D3D 10 Texture implementation. Creates a quad representing the view and | |
| 46 // a texture with the bitmap data. The quad has an origin of 0,0,0 with a size | |
| 47 // matching that of |SetCanvas|. | |
| 48 class ViewTexture : public Texture { | |
| 49 public: | |
| 50 ViewTexture(CompositorWin* compositor, | |
| 51 ID3D10Device* device, | |
| 52 ID3D10Effect* effect); | |
| 53 | |
| 54 // Texture: | |
| 55 virtual void SetCanvas(const SkCanvas& canvas, | |
| 56 const gfx::Point& origin, | |
| 57 const gfx::Size& overall_size) OVERRIDE; | |
| 58 virtual void Draw(const ui::TextureDrawParams& params, | |
| 59 const gfx::Rect& clip_bounds_in_texture) OVERRIDE; | |
| 60 | |
| 61 private: | |
| 62 ~ViewTexture(); | |
| 63 | |
| 64 void Errored(HRESULT result); | |
| 65 | |
| 66 void ConvertBitmapToD3DData(const SkBitmap& bitmap, | |
| 67 scoped_array<uint32>* converted_data); | |
| 68 | |
| 69 // Creates vertex buffer for specified region | |
| 70 void CreateVertexBufferForRegion(const gfx::Rect& bounds); | |
| 71 | |
| 72 scoped_refptr<CompositorWin> compositor_; | |
| 73 | |
| 74 // Size of the corresponding View. | |
| 75 gfx::Size view_size_; | |
| 76 | |
| 77 ScopedComPtr<ID3D10Device> device_; | |
| 78 ScopedComPtr<ID3D10Effect, NULL> effect_; | |
| 79 ScopedComPtr<ID3D10Texture2D> texture_; | |
| 80 ScopedComPtr<ID3D10ShaderResourceView> shader_view_; | |
| 81 ScopedComPtr<ID3D10Buffer> vertex_buffer_; | |
| 82 | |
| 83 DISALLOW_COPY_AND_ASSIGN(ViewTexture); | |
| 84 }; | |
| 85 | |
| 86 // D3D 10 Compositor implementation. | |
| 87 class CompositorWin : public Compositor { | |
| 88 public: | |
| 89 CompositorWin(CompositorDelegate* delegate, | |
| 90 gfx::AcceleratedWidget widget, | |
| 91 const gfx::Size& size); | |
| 92 | |
| 93 void Init(); | |
| 94 | |
| 95 // Invoked to update the perspective needed by this texture. |transform| is | |
| 96 // the transform for the texture, and |size| the size of the texture. | |
| 97 void UpdatePerspective(const ui::Transform& transform, | |
| 98 const gfx::Size& view_size); | |
| 99 | |
| 100 // Returns the index buffer used for drawing a texture. | |
| 101 ID3D10Buffer* GetTextureIndexBuffer(); | |
| 102 | |
| 103 // Compositor: | |
| 104 virtual Texture* CreateTexture() OVERRIDE; | |
| 105 | |
| 106 virtual void Blur(const gfx::Rect& bounds) OVERRIDE; | |
| 107 | |
| 108 virtual bool ReadPixels(SkBitmap* bitmap, const gfx::Rect& bounds) OVERRIDE; | |
| 109 | |
| 110 protected: | |
| 111 virtual void OnNotifyStart(bool clear) OVERRIDE; | |
| 112 virtual void OnNotifyEnd() OVERRIDE; | |
| 113 virtual void OnWidgetSizeChanged() OVERRIDE; | |
| 114 | |
| 115 private: | |
| 116 enum Direction { | |
| 117 HORIZONTAL, | |
| 118 VERTICAL | |
| 119 }; | |
| 120 | |
| 121 ~CompositorWin(); | |
| 122 | |
| 123 void Errored(HRESULT error_code); | |
| 124 | |
| 125 void CreateDevice(); | |
| 126 | |
| 127 void LoadEffects(); | |
| 128 | |
| 129 void InitVertexLayout(); | |
| 130 | |
| 131 // Updates the kernel used for blurring. Size is the size of the texture | |
| 132 // being drawn to along the appropriate axis. | |
| 133 void UpdateBlurKernel(Direction direction, int size); | |
| 134 | |
| 135 // Creates a texture, render target view and shader. | |
| 136 void CreateTexture(const gfx::Size& size, | |
| 137 ID3D10Texture2D** texture, | |
| 138 ID3D10RenderTargetView** render_target_view, | |
| 139 ID3D10ShaderResourceView** shader_resource_view); | |
| 140 | |
| 141 // Creates |vertex_buffer_|. | |
| 142 void CreateVertexBuffer(); | |
| 143 | |
| 144 // Creates |index_buffer_|. | |
| 145 void CreateIndexBuffer(); | |
| 146 | |
| 147 // Creates a vertex buffer for the specified region. The caller owns the | |
| 148 // return value. | |
| 149 ID3D10Buffer* CreateVertexBufferForRegion(const gfx::Rect& bounds); | |
| 150 | |
| 151 gfx::AcceleratedWidget host_; | |
| 152 | |
| 153 ScopedComPtr<ID3D10Device> device_; | |
| 154 ScopedComPtr<IDXGISwapChain> swap_chain_; | |
| 155 ScopedComPtr<ID3D10RenderTargetView> dest_render_target_view_; | |
| 156 ScopedComPtr<ID3D10Texture2D> depth_stencil_buffer_; | |
| 157 ScopedComPtr<ID3D10DepthStencilView> depth_stencil_view_; | |
| 158 ScopedComPtr<ID3D10Effect, NULL> fx_; | |
| 159 ID3D10EffectTechnique* technique_; | |
| 160 | |
| 161 // Layout for Vertex. | |
| 162 ScopedComPtr<ID3D10InputLayout> vertex_layout_; | |
| 163 | |
| 164 // Identity vertext buffer. Used when copying from main back to dest. | |
| 165 ScopedComPtr<ID3D10Buffer> vertex_buffer_; | |
| 166 | |
| 167 // Index buffer used for drawing a rectangle. | |
| 168 ScopedComPtr<ID3D10Buffer> index_buffer_; | |
| 169 | |
| 170 // Used for bluring. | |
| 171 ScopedComPtr<ID3D10Effect, NULL> blur_fx_; | |
| 172 ID3D10EffectTechnique* blur_technique_; | |
| 173 | |
| 174 // All rendering is done to the main_texture. Effects (such as bloom) render | |
| 175 // into the blur texture, and are then copied back to the main texture. When | |
| 176 // rendering is done |main_texture_| is drawn back to | |
| 177 // |dest_render_target_view_|. | |
| 178 ScopedComPtr<ID3D10Texture2D> main_texture_; | |
| 179 ScopedComPtr<ID3D10RenderTargetView> main_render_target_view_; | |
| 180 ScopedComPtr<ID3D10ShaderResourceView> main_texture_shader_view_; | |
| 181 | |
| 182 ScopedComPtr<ID3D10Texture2D> blur_texture_; | |
| 183 ScopedComPtr<ID3D10RenderTargetView> blur_render_target_view_; | |
| 184 ScopedComPtr<ID3D10ShaderResourceView> blur_texture_shader_view_; | |
| 185 | |
| 186 DISALLOW_COPY_AND_ASSIGN(CompositorWin); | |
| 187 }; | |
| 188 | |
| 189 ViewTexture::ViewTexture(CompositorWin* compositor, | |
| 190 ID3D10Device* device, | |
| 191 ID3D10Effect* effect) | |
| 192 : compositor_(compositor), | |
| 193 device_(device), | |
| 194 effect_(effect) { | |
| 195 } | |
| 196 | |
| 197 ViewTexture::~ViewTexture() { | |
| 198 } | |
| 199 | |
| 200 void ViewTexture::SetCanvas(const SkCanvas& canvas, | |
| 201 const gfx::Point& origin, | |
| 202 const gfx::Size& overall_size) { | |
| 203 view_size_ = overall_size; | |
| 204 | |
| 205 scoped_array<uint32> converted_data; | |
| 206 const SkBitmap& bitmap = canvas.getDevice()->accessBitmap(false); | |
| 207 ConvertBitmapToD3DData(bitmap, &converted_data); | |
| 208 if (gfx::Size(bitmap.width(), bitmap.height()) == overall_size) { | |
| 209 shader_view_.Release(); | |
| 210 texture_.Release(); | |
| 211 | |
| 212 D3D10_TEXTURE2D_DESC texture_desc; | |
| 213 texture_desc.Width = bitmap.width(); | |
| 214 texture_desc.Height = bitmap.height(); | |
| 215 texture_desc.MipLevels = 1; | |
| 216 texture_desc.ArraySize = 1; | |
| 217 texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; | |
| 218 texture_desc.SampleDesc.Count = 1; | |
| 219 texture_desc.SampleDesc.Quality = 0; | |
| 220 texture_desc.Usage = D3D10_USAGE_DEFAULT; | |
| 221 texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; | |
| 222 texture_desc.CPUAccessFlags = 0; | |
| 223 texture_desc.MiscFlags = 0; | |
| 224 RETURN_IF_FAILED(device_->CreateTexture2D(&texture_desc, | |
| 225 NULL, texture_.Receive())); | |
| 226 RETURN_IF_FAILED( | |
| 227 device_->CreateShaderResourceView(texture_.get(), NULL, | |
| 228 shader_view_.Receive())); | |
| 229 } | |
| 230 DCHECK(texture_.get()); | |
| 231 D3D10_BOX dst_box = { origin.x(), origin.y(), 0, | |
| 232 origin.x() + bitmap.width(), | |
| 233 origin.y() + bitmap.height(), 1 }; | |
| 234 device_->UpdateSubresource(texture_.get(), 0, &dst_box, | |
| 235 converted_data.get(), bitmap.width() * 4, 0); | |
| 236 } | |
| 237 | |
| 238 void ViewTexture::Draw(const ui::TextureDrawParams& params, | |
| 239 const gfx::Rect& clip_bounds) { | |
| 240 if (params.vertically_flipped) | |
| 241 NOTIMPLEMENTED(); | |
| 242 | |
| 243 compositor_->UpdatePerspective(params.transform, view_size_); | |
| 244 | |
| 245 // Make texture active. | |
| 246 RETURN_IF_FAILED( | |
| 247 effect_->GetVariableByName("textureMap")->AsShaderResource()-> | |
| 248 SetResource(shader_view_.get())); | |
| 249 | |
| 250 RETURN_IF_FAILED(effect_->GetVariableByName("alpha")->AsScalar()->SetFloat( | |
| 251 params.opacity)); | |
| 252 | |
| 253 ID3D10EffectTechnique* technique = effect_->GetTechniqueByName("ViewTech"); | |
| 254 DCHECK(technique); | |
| 255 D3D10_TECHNIQUE_DESC tech_desc; | |
| 256 technique->GetDesc(&tech_desc); | |
| 257 for(UINT p = 0; p < tech_desc.Passes; ++p) | |
| 258 technique->GetPassByIndex(p)->Apply(0); | |
| 259 | |
| 260 UINT stride = sizeof(Vertex); | |
| 261 UINT offset = 0; | |
| 262 CreateVertexBufferForRegion(clip_bounds); | |
| 263 ID3D10Buffer* vertex_buffer = vertex_buffer_.get(); | |
| 264 device_->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset); | |
| 265 device_->IASetIndexBuffer(compositor_->GetTextureIndexBuffer(), | |
| 266 DXGI_FORMAT_R32_UINT, 0); | |
| 267 device_->DrawIndexed(6, 0, 0); | |
| 268 } | |
| 269 | |
| 270 void ViewTexture::Errored(HRESULT result) { | |
| 271 // TODO: figure out error handling. | |
| 272 DCHECK(false); | |
| 273 } | |
| 274 | |
| 275 void ViewTexture::ConvertBitmapToD3DData( | |
| 276 const SkBitmap& bitmap, | |
| 277 scoped_array<uint32>* converted_data) { | |
| 278 int width = bitmap.width(); | |
| 279 int height = bitmap.height(); | |
| 280 SkAutoLockPixels pixel_lock(bitmap); | |
| 281 // D3D wants colors in ABGR format (premultiplied). | |
| 282 converted_data->reset(new uint32[width * height]); | |
| 283 uint32_t* bitmap_data = bitmap.getAddr32(0, 0); | |
| 284 for (int x = 0, offset = 0; x < width; ++x) { | |
| 285 for (int y = 0; y < height; ++y, ++offset) { | |
| 286 SkColor color = bitmap_data[offset]; | |
| 287 (*converted_data)[offset] = | |
| 288 (SkColorGetA(color) << 24) | | |
| 289 (SkColorGetB(color) << 16) | | |
| 290 (SkColorGetG(color) << 8) | | |
| 291 (SkColorGetR(color)); | |
| 292 } | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 void ViewTexture::CreateVertexBufferForRegion(const gfx::Rect& bounds) { | |
| 297 vertex_buffer_.Release(); | |
| 298 float x = bounds.x(); | |
| 299 float max_x = bounds.right(); | |
| 300 float y = bounds.y(); | |
| 301 float max_y = bounds.bottom(); | |
| 302 float tex_x = x / static_cast<float>(view_size_.width()); | |
| 303 float max_tex_x = max_x / static_cast<float>(view_size_.width()); | |
| 304 float tex_y = y / static_cast<float>(view_size_.width()); | |
| 305 float max_tex_y = max_y / static_cast<float>(view_size_.height()); | |
| 306 Vertex vertices[] = { | |
| 307 { D3DXVECTOR3( x, -max_y, 0.0f), D3DXVECTOR2( tex_x, max_tex_y) }, | |
| 308 { D3DXVECTOR3( x, -y, 0.0f), D3DXVECTOR2( tex_x, tex_y) }, | |
| 309 { D3DXVECTOR3(max_x, -y, 0.0f), D3DXVECTOR2(max_tex_x, tex_y) }, | |
| 310 { D3DXVECTOR3(max_x, -max_y, 0.0f), D3DXVECTOR2(max_tex_x, max_tex_y) } | |
| 311 }; | |
| 312 | |
| 313 // Create the vertex buffer containing the points. | |
| 314 D3D10_BUFFER_DESC buffer_desc; | |
| 315 buffer_desc.Usage = D3D10_USAGE_IMMUTABLE; | |
| 316 buffer_desc.ByteWidth = sizeof(Vertex) * ARRAYSIZE_UNSAFE(vertices); | |
| 317 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; | |
| 318 buffer_desc.CPUAccessFlags = 0; | |
| 319 buffer_desc.MiscFlags = 0; | |
| 320 D3D10_SUBRESOURCE_DATA init_data; | |
| 321 init_data.pSysMem = vertices; | |
| 322 RETURN_IF_FAILED(device_->CreateBuffer(&buffer_desc, &init_data, | |
| 323 vertex_buffer_.Receive())); | |
| 324 } | |
| 325 | |
| 326 CompositorWin::CompositorWin(CompositorDelegate* delegate, | |
| 327 gfx::AcceleratedWidget widget, | |
| 328 const gfx::Size& size) | |
| 329 : Compositor(delegate, size), | |
| 330 host_(widget), | |
| 331 technique_(NULL) { | |
| 332 } | |
| 333 | |
| 334 void CompositorWin::Init() { | |
| 335 CreateDevice(); | |
| 336 LoadEffects(); | |
| 337 OnWidgetSizeChanged(); | |
| 338 InitVertexLayout(); | |
| 339 CreateVertexBuffer(); | |
| 340 CreateIndexBuffer(); | |
| 341 } | |
| 342 | |
| 343 void CompositorWin::UpdatePerspective(const ui::Transform& transform, | |
| 344 const gfx::Size& view_size) { | |
| 345 float transform_data_buffer[16]; | |
| 346 transform.matrix().asColMajorf(transform_data_buffer); | |
| 347 D3DXMATRIX transform_matrix(&transform_data_buffer[0]); | |
| 348 std::swap(transform_matrix._12, transform_matrix._21); | |
| 349 std::swap(transform_matrix._13, transform_matrix._31); | |
| 350 std::swap(transform_matrix._23, transform_matrix._32); | |
| 351 | |
| 352 // Different coordinate system; flip the y. | |
| 353 transform_matrix._42 *= -1; | |
| 354 | |
| 355 // Scale so x and y are from 0-2. | |
| 356 D3DXMATRIX scale_matrix; | |
| 357 D3DXMatrixScaling( | |
| 358 &scale_matrix, | |
| 359 2.0f / static_cast<float>(size().width()), | |
| 360 2.0f / static_cast<float>(size().height()), | |
| 361 1.0f); | |
| 362 | |
| 363 // Translate so x and y are from -1,-1 to 1,1. | |
| 364 D3DXMATRIX translate_matrix; | |
| 365 D3DXMatrixTranslation(&translate_matrix, -1.0f, 1.0f, 0.0f); | |
| 366 | |
| 367 D3DXMATRIX projection_matrix; | |
| 368 D3DXMatrixIdentity(&projection_matrix); | |
| 369 D3DXMatrixPerspectiveFovLH(&projection_matrix, | |
| 370 atanf(.5f) * 2.0f, 1.0f, 1.0f, 1000.0f); | |
| 371 D3DXVECTOR3 pos(0.0f, 0.0f, -2.0f); | |
| 372 D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); | |
| 373 D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); | |
| 374 D3DXMATRIX view; | |
| 375 D3DXMatrixIdentity(&view); | |
| 376 D3DXMatrixLookAtLH(&view, &pos, &target, &up); | |
| 377 | |
| 378 D3DXMATRIX wvp = transform_matrix * scale_matrix * translate_matrix * view * | |
| 379 projection_matrix; | |
| 380 | |
| 381 fx_->GetVariableByName("gWVP")->AsMatrix()->SetMatrix(wvp); | |
| 382 } | |
| 383 | |
| 384 ID3D10Buffer* CompositorWin::GetTextureIndexBuffer() { | |
| 385 return index_buffer_.get(); | |
| 386 } | |
| 387 | |
| 388 Texture* CompositorWin::CreateTexture() { | |
| 389 return new ViewTexture(this, device_.get(), fx_.get()); | |
| 390 } | |
| 391 | |
| 392 void CompositorWin::OnNotifyStart(bool clear) { | |
| 393 ID3D10RenderTargetView* target_view = main_render_target_view_.get(); | |
| 394 device_->OMSetRenderTargets(1, &target_view, depth_stencil_view_.get()); | |
| 395 | |
| 396 // Clear the background and stencil view. | |
| 397 // TODO(vollick) see if |clear| can be used to avoid unnecessary clearing. | |
| 398 device_->ClearRenderTargetView(target_view, | |
| 399 D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.0f)); | |
| 400 device_->ClearDepthStencilView( | |
| 401 depth_stencil_view_.get(), D3D10_CLEAR_DEPTH|D3D10_CLEAR_STENCIL, | |
| 402 1.0f, 0); | |
| 403 | |
| 404 // TODO: these steps may not be necessary each time through. | |
| 405 device_->OMSetDepthStencilState(0, 0); | |
| 406 float blend_factors[] = {0.0f, 0.0f, 0.0f, 0.0f}; | |
| 407 device_->OMSetBlendState(0, blend_factors, 0xffffffff); | |
| 408 device_->IASetInputLayout(vertex_layout_.get()); | |
| 409 device_->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); | |
| 410 } | |
| 411 | |
| 412 void CompositorWin::OnNotifyEnd() { | |
| 413 // Copy from main_render_target_view_| (where all are rendering was done) back | |
| 414 // to |dest_render_target_view_|. | |
| 415 ID3D10RenderTargetView* target_view = dest_render_target_view_.get(); | |
| 416 device_->OMSetRenderTargets(1, &target_view, NULL); | |
| 417 device_->ClearRenderTargetView(target_view, | |
| 418 D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.0f)); | |
| 419 RETURN_IF_FAILED( | |
| 420 fx_->GetVariableByName("textureMap")->AsShaderResource()-> | |
| 421 SetResource(main_texture_shader_view_.get())); | |
| 422 D3DXMATRIX identify_matrix; | |
| 423 D3DXMatrixIdentity(&identify_matrix); | |
| 424 fx_->GetVariableByName("gWVP")->AsMatrix()->SetMatrix(identify_matrix); | |
| 425 ID3D10EffectTechnique* technique = fx_->GetTechniqueByName("ViewTech"); | |
| 426 DCHECK(technique); | |
| 427 D3D10_TECHNIQUE_DESC tech_desc; | |
| 428 technique->GetDesc(&tech_desc); | |
| 429 for(UINT p = 0; p < tech_desc.Passes; ++p) | |
| 430 technique->GetPassByIndex(p)->Apply(0); | |
| 431 UINT stride = sizeof(Vertex); | |
| 432 UINT offset = 0; | |
| 433 ID3D10Buffer* vertex_buffer = vertex_buffer_.get(); | |
| 434 device_->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset); | |
| 435 device_->IASetIndexBuffer(index_buffer_.get(), DXGI_FORMAT_R32_UINT, 0); | |
| 436 device_->DrawIndexed(6, 0, 0); | |
| 437 RETURN_IF_FAILED( | |
| 438 fx_->GetVariableByName("textureMap")->AsShaderResource()-> | |
| 439 SetResource(NULL)); | |
| 440 swap_chain_->Present(0, 0); | |
| 441 | |
| 442 // We may delete the shader resource view before drawing again. Unset it so | |
| 443 // that d3d doesn't generate a warning when we do that. | |
| 444 fx_->GetVariableByName("textureMap")->AsShaderResource()->SetResource(NULL); | |
| 445 for(UINT i = 0; i < tech_desc.Passes; ++i) | |
| 446 technique_->GetPassByIndex(i)->Apply(0); | |
| 447 } | |
| 448 | |
| 449 void CompositorWin::Blur(const gfx::Rect& bounds) { | |
| 450 // Set up the vertex buffer for the region we're going to blur. | |
| 451 ScopedComPtr<ID3D10Buffer> scoped_vertex_buffer( | |
| 452 CreateVertexBufferForRegion(bounds)); | |
| 453 ID3D10Buffer* vertex_buffer = scoped_vertex_buffer.get(); | |
| 454 UINT stride = sizeof(Vertex); | |
| 455 UINT offset = 0; | |
| 456 device_->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset); | |
| 457 device_->IASetIndexBuffer(index_buffer_.get(), DXGI_FORMAT_R32_UINT, 0); | |
| 458 device_->DrawIndexed(6, 0, 0); | |
| 459 D3DXMATRIX identity_matrix; | |
| 460 D3DXMatrixIdentity(&identity_matrix); | |
| 461 | |
| 462 // Horizontal blur from the main texture to blur texture. | |
| 463 UpdateBlurKernel(HORIZONTAL, size().width()); | |
| 464 ID3D10RenderTargetView* target_view = blur_render_target_view_.get(); | |
| 465 device_->OMSetRenderTargets(1, &target_view, NULL); | |
| 466 RETURN_IF_FAILED( | |
| 467 blur_fx_->GetVariableByName("textureMap")->AsShaderResource()-> | |
| 468 SetResource(main_texture_shader_view_.get())); | |
| 469 blur_fx_->GetVariableByName("gWVP")->AsMatrix()->SetMatrix( | |
| 470 identity_matrix); | |
| 471 ID3D10EffectTechnique* technique = blur_fx_->GetTechniqueByName("ViewTech"); | |
| 472 DCHECK(technique); | |
| 473 D3D10_TECHNIQUE_DESC tech_desc; | |
| 474 technique->GetDesc(&tech_desc); | |
| 475 for(UINT p = 0; p < tech_desc.Passes; ++p) | |
| 476 technique->GetPassByIndex(p)->Apply(0); | |
| 477 device_->DrawIndexed(6, 0, 0); | |
| 478 | |
| 479 { | |
| 480 // We do this to avoid a warning. | |
| 481 ID3D10ShaderResourceView* tmp = NULL; | |
| 482 device_->PSSetShaderResources(0, 1, &tmp); | |
| 483 } | |
| 484 | |
| 485 // Vertical blur from the blur texture back to main buffer. | |
| 486 RETURN_IF_FAILED( | |
| 487 blur_fx_->GetVariableByName("textureMap")->AsShaderResource()-> | |
| 488 SetResource(blur_texture_shader_view_.get())); | |
| 489 UpdateBlurKernel(VERTICAL, size().height()); | |
| 490 target_view = main_render_target_view_.get(); | |
| 491 device_->OMSetRenderTargets(1, &target_view, NULL); | |
| 492 for(UINT p = 0; p < tech_desc.Passes; ++p) | |
| 493 technique->GetPassByIndex(p)->Apply(0); | |
| 494 device_->DrawIndexed(6, 0, 0); | |
| 495 | |
| 496 #if !defined(NDEBUG) | |
| 497 // A warning is generated if a bound vertexbuffer is deleted. To avoid that | |
| 498 // warning we reset the buffer here. We only do it for debug builds as it's | |
| 499 // ok to effectively unbind the vertex buffer. | |
| 500 vertex_buffer = vertex_buffer_.get(); | |
| 501 device_->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset); | |
| 502 device_->IASetIndexBuffer(index_buffer_.get(), DXGI_FORMAT_R32_UINT, 0); | |
| 503 #endif | |
| 504 } | |
| 505 | |
| 506 bool CompositorWin::ReadPixels(SkBitmap* bitmap, const gfx::Rect& bounds) { | |
| 507 NOTIMPLEMENTED(); | |
| 508 return false; | |
| 509 } | |
| 510 | |
| 511 void CompositorWin::OnWidgetSizeChanged() { | |
| 512 dest_render_target_view_ = NULL; | |
| 513 depth_stencil_buffer_ = NULL; | |
| 514 depth_stencil_view_ = NULL; | |
| 515 | |
| 516 main_render_target_view_ = NULL; | |
| 517 main_texture_ = NULL; | |
| 518 main_texture_shader_view_ = NULL; | |
| 519 | |
| 520 blur_render_target_view_ = NULL; | |
| 521 blur_texture_ = NULL; | |
| 522 blur_texture_shader_view_ = NULL; | |
| 523 | |
| 524 CreateTexture(size(), main_texture_.Receive(), | |
| 525 main_render_target_view_.Receive(), | |
| 526 main_texture_shader_view_.Receive()); | |
| 527 | |
| 528 CreateTexture(size(), blur_texture_.Receive(), | |
| 529 blur_render_target_view_.Receive(), | |
| 530 blur_texture_shader_view_.Receive()); | |
| 531 | |
| 532 // Resize the swap chain and recreate the render target view. | |
| 533 RETURN_IF_FAILED(swap_chain_->ResizeBuffers( | |
| 534 1, size().width(), size().height(), DXGI_FORMAT_R8G8B8A8_UNORM, 0)); | |
| 535 ScopedComPtr<ID3D10Texture2D> back_buffer; | |
| 536 RETURN_IF_FAILED(swap_chain_->GetBuffer( | |
| 537 0, __uuidof(ID3D10Texture2D), | |
| 538 reinterpret_cast<void**>(back_buffer.Receive()))); | |
| 539 RETURN_IF_FAILED(device_->CreateRenderTargetView( | |
| 540 back_buffer.get(), 0, | |
| 541 dest_render_target_view_.Receive())); | |
| 542 | |
| 543 // Create the depth/stencil buffer and view. | |
| 544 D3D10_TEXTURE2D_DESC depth_stencil_desc; | |
| 545 depth_stencil_desc.Width = size().width(); | |
| 546 depth_stencil_desc.Height = size().height(); | |
| 547 depth_stencil_desc.MipLevels = 1; | |
| 548 depth_stencil_desc.ArraySize = 1; | |
| 549 depth_stencil_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; | |
| 550 depth_stencil_desc.SampleDesc.Count = 1; // multisampling must match | |
| 551 depth_stencil_desc.SampleDesc.Quality = 0; // swap chain values. | |
| 552 depth_stencil_desc.Usage = D3D10_USAGE_DEFAULT; | |
| 553 depth_stencil_desc.BindFlags = D3D10_BIND_DEPTH_STENCIL; | |
| 554 depth_stencil_desc.CPUAccessFlags = 0; | |
| 555 depth_stencil_desc.MiscFlags = 0; | |
| 556 | |
| 557 RETURN_IF_FAILED(device_->CreateTexture2D(&depth_stencil_desc, 0, | |
| 558 depth_stencil_buffer_.Receive())); | |
| 559 RETURN_IF_FAILED(device_->CreateDepthStencilView( | |
| 560 depth_stencil_buffer_.get(), 0, | |
| 561 depth_stencil_view_.Receive())); | |
| 562 | |
| 563 | |
| 564 // Set the viewport transform. | |
| 565 D3D10_VIEWPORT vp; | |
| 566 vp.TopLeftX = 0; | |
| 567 vp.TopLeftY = 0; | |
| 568 vp.Width = size().width(); | |
| 569 vp.Height = size().height(); | |
| 570 vp.MinDepth = 0.0f; | |
| 571 vp.MaxDepth = 1.0f; | |
| 572 | |
| 573 device_->RSSetViewports(1, &vp); | |
| 574 } | |
| 575 | |
| 576 CompositorWin::~CompositorWin() { | |
| 577 } | |
| 578 | |
| 579 void CompositorWin::Errored(HRESULT error_code) { | |
| 580 // TODO: figure out error handling. | |
| 581 DCHECK(false); | |
| 582 } | |
| 583 | |
| 584 void CompositorWin::CreateDevice() { | |
| 585 DXGI_SWAP_CHAIN_DESC sd; | |
| 586 sd.BufferDesc.Width = size().width(); | |
| 587 sd.BufferDesc.Height = size().height(); | |
| 588 sd.BufferDesc.RefreshRate.Numerator = 60; | |
| 589 sd.BufferDesc.RefreshRate.Denominator = 1; | |
| 590 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; | |
| 591 sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; | |
| 592 sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; | |
| 593 | |
| 594 // No multisampling. | |
| 595 sd.SampleDesc.Count = 1; | |
| 596 sd.SampleDesc.Quality = 0; | |
| 597 | |
| 598 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; | |
| 599 sd.BufferCount = 1; | |
| 600 sd.OutputWindow = host_; | |
| 601 sd.Windowed = true; | |
| 602 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; | |
| 603 sd.Flags = 0; | |
| 604 | |
| 605 // Create the device. | |
| 606 UINT createDeviceFlags = 0; | |
| 607 #if !defined(NDEBUG) | |
| 608 createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; | |
| 609 #endif | |
| 610 RETURN_IF_FAILED( | |
| 611 D3D10CreateDeviceAndSwapChain( | |
| 612 0, //default adapter | |
| 613 D3D10_DRIVER_TYPE_HARDWARE, | |
| 614 0, // no software device | |
| 615 createDeviceFlags, | |
| 616 D3D10_SDK_VERSION, | |
| 617 &sd, | |
| 618 swap_chain_.Receive(), | |
| 619 device_.Receive())); | |
| 620 } | |
| 621 | |
| 622 void CompositorWin::LoadEffects() { | |
| 623 DWORD shader_flags = D3D10_SHADER_ENABLE_STRICTNESS; | |
| 624 #if !defined(NDEBUG) | |
| 625 shader_flags |= D3D10_SHADER_DEBUG | D3D10_SHADER_SKIP_OPTIMIZATION; | |
| 626 #endif | |
| 627 ScopedComPtr<ID3D10Blob> compilation_errors; | |
| 628 const base::StringPiece& fx_data = ResourceBundle::GetSharedInstance(). | |
| 629 GetRawDataResource(IDR_COMPOSITOR_FX); | |
| 630 DCHECK(!fx_data.empty()); | |
| 631 RETURN_IF_FAILED( | |
| 632 D3DX10CreateEffectFromMemory( | |
| 633 fx_data.data(), fx_data.size(), "compositor.fx", NULL, NULL, | |
| 634 "fx_4_0", shader_flags, 0, device_.get(), NULL, NULL, fx_.Receive(), | |
| 635 compilation_errors.Receive(), NULL)); | |
| 636 technique_ = fx_->GetTechniqueByName("ViewTech"); | |
| 637 DCHECK(technique_); | |
| 638 | |
| 639 const base::StringPiece& blur_data = ResourceBundle::GetSharedInstance(). | |
| 640 GetRawDataResource(IDR_BLUR_FX); | |
| 641 DCHECK(!blur_data.empty()); | |
| 642 compilation_errors = NULL; | |
| 643 RETURN_IF_FAILED( | |
| 644 D3DX10CreateEffectFromMemory( | |
| 645 blur_data.data(), blur_data.size(), "bloom.fx", NULL, NULL, | |
| 646 "fx_4_0", shader_flags, 0, device_.get(), NULL, NULL, | |
| 647 blur_fx_.Receive(), compilation_errors.Receive(), NULL)); | |
| 648 blur_technique_ = blur_fx_->GetTechniqueByName("ViewTech"); | |
| 649 DCHECK(blur_technique_); | |
| 650 } | |
| 651 | |
| 652 void CompositorWin::InitVertexLayout() { | |
| 653 D3D10_INPUT_ELEMENT_DESC vertex_desc[] = { | |
| 654 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, | |
| 655 D3D10_INPUT_PER_VERTEX_DATA, 0 }, | |
| 656 { "TEXC", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, | |
| 657 D3D10_INPUT_PER_VERTEX_DATA, 0 }, | |
| 658 }; | |
| 659 | |
| 660 // Create the input layout | |
| 661 D3D10_PASS_DESC pass_desc; | |
| 662 RETURN_IF_FAILED(technique_->GetPassByIndex(0)->GetDesc(&pass_desc)); | |
| 663 RETURN_IF_FAILED( | |
| 664 device_->CreateInputLayout(vertex_desc, ARRAYSIZE_UNSAFE(vertex_desc), | |
| 665 pass_desc.pIAInputSignature, | |
| 666 pass_desc.IAInputSignatureSize, | |
| 667 vertex_layout_.Receive())); | |
| 668 } | |
| 669 | |
| 670 void CompositorWin::UpdateBlurKernel(Direction direction, int size) { | |
| 671 // Update the blur data. | |
| 672 const int kSize = 13; | |
| 673 float pixel_data[4 * kSize]; | |
| 674 memset(pixel_data, 0, sizeof(float) * 4 * kSize); | |
| 675 for (int i = 0; i < kSize; ++i) { | |
| 676 pixel_data[i * 4 + ((direction == HORIZONTAL) ? 0 : 1)] = | |
| 677 static_cast<float>(i - (kSize / 2)) / static_cast<float>(size); | |
| 678 } | |
| 679 RETURN_IF_FAILED(blur_fx_->GetVariableByName("TexelKernel")->AsVector()-> | |
| 680 SetFloatVectorArray(pixel_data, 0, kSize)); | |
| 681 } | |
| 682 | |
| 683 void CompositorWin::CreateTexture( | |
| 684 const gfx::Size& size, | |
| 685 ID3D10Texture2D** texture, | |
| 686 ID3D10RenderTargetView** render_target_view, | |
| 687 ID3D10ShaderResourceView** shader_resource_view) { | |
| 688 D3D10_TEXTURE2D_DESC texture_desc; | |
| 689 texture_desc.Width = size.width(); | |
| 690 texture_desc.Height = size.height(); | |
| 691 texture_desc.MipLevels = 1; | |
| 692 texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; | |
| 693 texture_desc.SampleDesc.Count = 1; | |
| 694 texture_desc.SampleDesc.Quality = 0; | |
| 695 texture_desc.Usage = D3D10_USAGE_DEFAULT; | |
| 696 texture_desc.BindFlags = | |
| 697 D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; | |
| 698 texture_desc.CPUAccessFlags = 0; | |
| 699 texture_desc.MiscFlags = 0; | |
| 700 texture_desc.ArraySize = 1; | |
| 701 RETURN_IF_FAILED(device_->CreateTexture2D(&texture_desc, NULL, texture)); | |
| 702 | |
| 703 RETURN_IF_FAILED( | |
| 704 device_->CreateShaderResourceView(*texture, NULL, shader_resource_view)); | |
| 705 | |
| 706 D3D10_RENDER_TARGET_VIEW_DESC render_target_view_desc; | |
| 707 render_target_view_desc.Format = texture_desc.Format; | |
| 708 render_target_view_desc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2DMS; | |
| 709 render_target_view_desc.Texture2D.MipSlice = 0; | |
| 710 RETURN_IF_FAILED(device_->CreateRenderTargetView( | |
| 711 *texture, &render_target_view_desc, render_target_view)); | |
| 712 } | |
| 713 | |
| 714 void CompositorWin::CreateVertexBuffer() { | |
| 715 vertex_buffer_.Release(); | |
| 716 | |
| 717 Vertex vertices[] = { | |
| 718 { D3DXVECTOR3(-1.0f, -1.0f, 0.0f), D3DXVECTOR2(0.0f, 1.0f) }, | |
| 719 { D3DXVECTOR3(-1.0f, 1.0f, 0.0f), D3DXVECTOR2(0.0f, 0.0f) }, | |
| 720 { D3DXVECTOR3( 1.0f, 1.0f, 0.0f), D3DXVECTOR2(1.0f, 0.0f) }, | |
| 721 { D3DXVECTOR3( 1.0f, -1.0f, 0.0f), D3DXVECTOR2(1.0f, 1.0f) }, | |
| 722 }; | |
| 723 | |
| 724 // Create the vertex buffer containing the points. | |
| 725 D3D10_BUFFER_DESC buffer_desc; | |
| 726 buffer_desc.Usage = D3D10_USAGE_IMMUTABLE; | |
| 727 buffer_desc.ByteWidth = sizeof(Vertex) * ARRAYSIZE_UNSAFE(vertices); | |
| 728 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; | |
| 729 buffer_desc.CPUAccessFlags = 0; | |
| 730 buffer_desc.MiscFlags = 0; | |
| 731 D3D10_SUBRESOURCE_DATA init_data; | |
| 732 init_data.pSysMem = vertices; | |
| 733 RETURN_IF_FAILED(device_->CreateBuffer(&buffer_desc, &init_data, | |
| 734 vertex_buffer_.Receive())); | |
| 735 } | |
| 736 | |
| 737 void CompositorWin::CreateIndexBuffer() { | |
| 738 index_buffer_.Release(); | |
| 739 | |
| 740 // Then the index buffer. | |
| 741 DWORD indices[] = { | |
| 742 0, 1, 2, | |
| 743 0, 2, 3, | |
| 744 }; | |
| 745 D3D10_BUFFER_DESC index_buffer; | |
| 746 index_buffer.Usage = D3D10_USAGE_IMMUTABLE; | |
| 747 index_buffer.ByteWidth = sizeof(DWORD) * ARRAYSIZE_UNSAFE(indices); | |
| 748 index_buffer.BindFlags = D3D10_BIND_INDEX_BUFFER; | |
| 749 index_buffer.CPUAccessFlags = 0; | |
| 750 index_buffer.MiscFlags = 0; | |
| 751 D3D10_SUBRESOURCE_DATA init_data; | |
| 752 init_data.pSysMem = indices; | |
| 753 RETURN_IF_FAILED(device_->CreateBuffer(&index_buffer, &init_data, | |
| 754 index_buffer_.Receive())); | |
| 755 } | |
| 756 | |
| 757 ID3D10Buffer* CompositorWin::CreateVertexBufferForRegion( | |
| 758 const gfx::Rect& bounds) { | |
| 759 float x = static_cast<float>(bounds.x()) / | |
| 760 static_cast<float>(size().width()) * 2.0f - 1.0f; | |
| 761 float max_x = | |
| 762 x + bounds.width() / static_cast<float>(size().width()) * 2.0f; | |
| 763 float y = | |
| 764 static_cast<float>(size().height() - bounds.y() - bounds.height()) / | |
| 765 static_cast<float>(size().height()) * 2.0f - 1.0f; | |
| 766 float max_y = | |
| 767 y + bounds.height() / static_cast<float>(size().height()) * 2.0f; | |
| 768 float tex_x = x / 2.0f + .5f; | |
| 769 float max_tex_x = max_x / 2.0f + .5f; | |
| 770 float tex_y = 1.0f - (max_y + 1.0f) / 2.0f; | |
| 771 float max_tex_y = tex_y + (max_y - y) / 2.0f; | |
| 772 Vertex vertices[] = { | |
| 773 { D3DXVECTOR3( x, y, 0.0f), D3DXVECTOR2( tex_x, max_tex_y) }, | |
| 774 { D3DXVECTOR3( x, max_y, 0.0f), D3DXVECTOR2( tex_x, tex_y) }, | |
| 775 { D3DXVECTOR3(max_x, max_y, 0.0f), D3DXVECTOR2(max_tex_x, tex_y) }, | |
| 776 { D3DXVECTOR3(max_x, y, 0.0f), D3DXVECTOR2(max_tex_x, max_tex_y) }, | |
| 777 }; | |
| 778 | |
| 779 // Create the vertex buffer containing the points. | |
| 780 D3D10_BUFFER_DESC buffer_desc; | |
| 781 buffer_desc.Usage = D3D10_USAGE_IMMUTABLE; | |
| 782 buffer_desc.ByteWidth = sizeof(Vertex) * ARRAYSIZE_UNSAFE(vertices); | |
| 783 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; | |
| 784 buffer_desc.CPUAccessFlags = 0; | |
| 785 buffer_desc.MiscFlags = 0; | |
| 786 D3D10_SUBRESOURCE_DATA init_data; | |
| 787 init_data.pSysMem = vertices; | |
| 788 ID3D10Buffer* vertex_buffer = NULL; | |
| 789 // TODO: better error handling. | |
| 790 int error_code = | |
| 791 device_->CreateBuffer(&buffer_desc, &init_data, &vertex_buffer); | |
| 792 if (error_code != S_OK) { | |
| 793 Errored(error_code); | |
| 794 return NULL; | |
| 795 } | |
| 796 return vertex_buffer; | |
| 797 } | |
| 798 | |
| 799 } // namespace | |
| 800 | |
| 801 // static | |
| 802 Compositor* Compositor::Create(CompositorDelegate* delegate, | |
| 803 gfx::AcceleratedWidget widget, | |
| 804 const gfx::Size& size) { | |
| 805 CompositorWin* compositor = new CompositorWin(delegate, widget, size); | |
| 806 compositor->Init(); | |
| 807 return compositor; | |
| 808 } | |
| 809 | |
| 810 } // namespace ui | |
| OLD | NEW |