| Index: ui/surface/accelerated_surface_win.cc | 
| =================================================================== | 
| --- ui/surface/accelerated_surface_win.cc	(revision 142394) | 
| +++ ui/surface/accelerated_surface_win.cc	(working copy) | 
| @@ -34,7 +34,84 @@ | 
|  | 
| const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; | 
| const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; | 
| +const char kReverseImageTransportSurfaceRows[] = | 
| +    "reverse-image-transport-surface-rows"; | 
|  | 
| +struct Vertex { | 
| +  float x, y, z, w; | 
| +  float u, v; | 
| +}; | 
| + | 
| +// See accelerated_surface_win.hlsl for source and compilation instructions. | 
| +const BYTE g_vertexMain[] = { | 
| +    0,   2, 254, 255, 254, 255, | 
| +   22,   0,  67,  84,  65,  66, | 
| +   28,   0,   0,   0,  35,   0, | 
| +    0,   0,   0,   2, 254, 255, | 
| +    0,   0,   0,   0,   0,   0, | 
| +    0,   0,   0,   1,   0,   0, | 
| +   28,   0,   0,   0, 118, 115, | 
| +   95,  50,  95,  48,   0,  77, | 
| +  105,  99, 114, 111, 115, 111, | 
| +  102, 116,  32,  40,  82,  41, | 
| +   32,  72,  76,  83,  76,  32, | 
| +   83, 104,  97, 100, 101, 114, | 
| +   32,  67, 111, 109, 112, 105, | 
| +  108, 101, 114,  32,  57,  46, | 
| +   50,  57,  46,  57,  53,  50, | 
| +   46,  51,  49,  49,  49,   0, | 
| +   31,   0,   0,   2,   0,   0, | 
| +    0, 128,   0,   0,  15, 144, | 
| +   31,   0,   0,   2,   5,   0, | 
| +    0, 128,   1,   0,  15, 144, | 
| +    1,   0,   0,   2,   0,   0, | 
| +   15, 192,   0,   0, 228, 144, | 
| +    1,   0,   0,   2,   0,   0, | 
| +    3, 224,   1,   0, 228, 144, | 
| +  255, 255,   0,   0 | 
| +}; | 
| + | 
| +const BYTE g_pixelMain[] = { | 
| +    0,   2, 255, 255, 254, 255, | 
| +   32,   0,  67,  84,  65,  66, | 
| +   28,   0,   0,   0,  75,   0, | 
| +    0,   0,   0,   2, 255, 255, | 
| +    1,   0,   0,   0,  28,   0, | 
| +    0,   0,   0,   1,   0,   0, | 
| +   68,   0,   0,   0,  48,   0, | 
| +    0,   0,   3,   0,   0,   0, | 
| +    1,   0,   0,   0,  52,   0, | 
| +    0,   0,   0,   0,   0,   0, | 
| +  115,   0, 171, 171,   4,   0, | 
| +   12,   0,   1,   0,   1,   0, | 
| +    1,   0,   0,   0,   0,   0, | 
| +    0,   0, 112, 115,  95,  50, | 
| +   95,  48,   0,  77, 105,  99, | 
| +  114, 111, 115, 111, 102, 116, | 
| +   32,  40,  82,  41,  32,  72, | 
| +   76,  83,  76,  32,  83, 104, | 
| +   97, 100, 101, 114,  32,  67, | 
| +  111, 109, 112, 105, 108, 101, | 
| +  114,  32,  57,  46,  50,  57, | 
| +   46,  57,  53,  50,  46,  51, | 
| +   49,  49,  49,   0,  31,   0, | 
| +    0,   2,   0,   0,   0, 128, | 
| +    0,   0,   3, 176,  31,   0, | 
| +    0,   2,   0,   0,   0, 144, | 
| +    0,   8,  15, 160,  66,   0, | 
| +    0,   3,   0,   0,  15, 128, | 
| +    0,   0, 228, 176,   0,   8, | 
| +  228, 160,   1,   0,   0,   2, | 
| +    0,   8,  15, 128,   0,   0, | 
| +  228, 128, 255, 255,   0,   0 | 
| +}; | 
| + | 
| +const static D3DVERTEXELEMENT9 g_vertexElements[] = { | 
| +  { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0 }, | 
| +  { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 }, | 
| +  D3DDECL_END() | 
| +}; | 
| + | 
| UINT GetPresentationInterval() { | 
| if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) | 
| return D3DPRESENT_INTERVAL_IMMEDIATE; | 
| @@ -212,8 +289,44 @@ | 
| return; | 
|  | 
| hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); | 
| -  if (FAILED(hr)) | 
| +  if (FAILED(hr)) { | 
| device_ = NULL; | 
| +    return; | 
| +  } | 
| + | 
| +  base::win::ScopedComPtr<IDirect3DVertexShader9> vertex_shader; | 
| +  hr = device_->CreateVertexShader(reinterpret_cast<const DWORD*>(g_vertexMain), | 
| +                                   vertex_shader.Receive()); | 
| +  if (FAILED(hr)) { | 
| +    device_ = NULL; | 
| +    query_ = NULL; | 
| +    return; | 
| +  } | 
| + | 
| +  device_->SetVertexShader(vertex_shader); | 
| + | 
| +  base::win::ScopedComPtr<IDirect3DPixelShader9> pixel_shader; | 
| +  hr = device_->CreatePixelShader(reinterpret_cast<const DWORD*>(g_pixelMain), | 
| +                                  pixel_shader.Receive()); | 
| + | 
| +  if (FAILED(hr)) { | 
| +    device_ = NULL; | 
| +    query_ = NULL; | 
| +    return; | 
| +  } | 
| + | 
| +  device_->SetPixelShader(pixel_shader); | 
| + | 
| +  base::win::ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration; | 
| +  hr = device_->CreateVertexDeclaration(g_vertexElements, | 
| +                                        vertex_declaration.Receive()); | 
| +  if (FAILED(hr)) { | 
| +    device_ = NULL; | 
| +    query_ = NULL; | 
| +    return; | 
| +  } | 
| + | 
| +  device_->SetVertexDeclaration(vertex_declaration); | 
| } | 
|  | 
| void PresentThread::CleanUp() { | 
| @@ -287,6 +400,8 @@ | 
| window_(window), | 
| event_(false, false), | 
| hidden_(true) { | 
| +  reverse_rows_ = CommandLine::ForCurrentProcess()->HasSwitch( | 
| +      kReverseImageTransportSurfaceRows); | 
| } | 
|  | 
| scoped_refptr<AcceleratedPresenter> AcceleratedPresenter::GetForWindow( | 
| @@ -634,14 +749,54 @@ | 
| }; | 
|  | 
| { | 
| -    TRACE_EVENT0("gpu", "StretchRect"); | 
| -    hr = present_thread_->device()->StretchRect(source_surface, | 
| -                                                &rect, | 
| -                                                dest_surface, | 
| -                                                &rect, | 
| -                                                D3DTEXF_NONE); | 
| -    if (FAILED(hr)) | 
| -      return; | 
| +    TRACE_EVENT0("gpu", "Copy"); | 
| + | 
| +    if (reverse_rows_) { | 
| +      // Use a simple pixel / vertex shader pair to render a quad that flips the | 
| +      // source texture on the vertical axis. | 
| +      IDirect3DSurface9 *default_render_target = NULL; | 
| +      present_thread_->device()->GetRenderTarget(0, &default_render_target); | 
| + | 
| +      present_thread_->device()->SetRenderTarget(0, dest_surface); | 
| +      present_thread_->device()->SetTexture(0, source_texture_); | 
| + | 
| +      D3DVIEWPORT9 viewport = { | 
| +        0, 0, | 
| +        size.width(), size.height(), | 
| +        0, 1 | 
| +      }; | 
| +      present_thread_->device()->SetViewport(&viewport); | 
| + | 
| +      float halfPixelX = -1.0f / size.width(); | 
| +      float halfPixelY = 1.0f / size.height(); | 
| +      Vertex vertices[] = { | 
| +        { halfPixelX - 1, halfPixelY + 1, 0.5f, 1, 0, 1 }, | 
| +        { halfPixelX + 1, halfPixelY + 1, 0.5f, 1, 1, 1 }, | 
| +        { halfPixelX + 1, halfPixelY - 1, 0.5f, 1, 1, 0 }, | 
| +        { halfPixelX - 1, halfPixelY - 1, 0.5f, 1, 0, 0 } | 
| +      }; | 
| + | 
| +      present_thread_->device()->BeginScene(); | 
| +      present_thread_->device()->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, | 
| +                                                 arraysize(vertices), | 
| +                                                 vertices, | 
| +                                                 sizeof(vertices[0])); | 
| +      present_thread_->device()->EndScene(); | 
| + | 
| +      present_thread_->device()->SetTexture(0, NULL); | 
| +      present_thread_->device()->SetRenderTarget(0, default_render_target); | 
| +      default_render_target->Release(); | 
| +    } else { | 
| +      // Copy the source texture directly into the swap chain without reversing | 
| +      // the rows. | 
| +      hr = present_thread_->device()->StretchRect(source_surface, | 
| +                                                  &rect, | 
| +                                                  dest_surface, | 
| +                                                  &rect, | 
| +                                                  D3DTEXF_NONE); | 
| +      if (FAILED(hr)) | 
| +        return; | 
| +    } | 
| } | 
|  | 
| hr = present_thread_->query()->Issue(D3DISSUE_END); | 
|  |