15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/software_output_device_win.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkDevice.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/compositor.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/canvas.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/canvas_skia_paint.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/gdi_util.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/skia_util.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(ui::Compositor* compositor)
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : hwnd_(compositor->widget()),
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      is_hwnd_composited_(false) {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(skaslev) Remove this when crbug.com/180702 is fixed.
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LONG style = GetWindowLong(hwnd_, GWL_EXSTYLE);
250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  is_hwnd_composited_ = !!(style & WS_EX_COMPOSITED);
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size,
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     float scale_factor) {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scale_factor_ = scale_factor;
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (viewport_pixel_size_ == viewport_pixel_size)
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  viewport_pixel_size_ = viewport_pixel_size;
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  contents_.reset(new gfx::Canvas(viewport_pixel_size, 1.0f, true));
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(&bitmap_info_, 0, sizeof(bitmap_info_));
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gfx::CreateBitmapHeader(viewport_pixel_size_.width(),
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          viewport_pixel_size_.height(),
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          &bitmap_info_.bmiHeader);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) {
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(contents_);
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  damage_rect_ = damage_rect;
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return contents_ ? contents_->sk_canvas() : NULL;
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SoftwareOutputDeviceWin::EndPaint(cc::SoftwareFrameData* frame_data) {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(contents_);
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(frame_data);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!contents_)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SoftwareOutputDevice::EndPaint(frame_data);
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect rect = damage_rect_;
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rect.Intersect(gfx::Rect(viewport_pixel_size_));
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rect.IsEmpty())
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkCanvas* canvas = contents_->sk_canvas();
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(canvas);
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (is_hwnd_composited_) {
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RECT wr;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GetWindowRect(hwnd_, &wr);
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SIZE size = {wr.right - wr.left, wr.bottom - wr.top};
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    POINT position = {wr.left, wr.top};
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    POINT zero = {0, 0};
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    BLENDFUNCTION blend = {AC_SRC_OVER, 0x00, 0xFF, AC_SRC_ALPHA};
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DWORD style = GetWindowLong(hwnd_, GWL_EXSTYLE);
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    style &= ~WS_EX_COMPOSITED;
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    style |= WS_EX_LAYERED;
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SetWindowLong(hwnd_, GWL_EXSTYLE, style);
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    HDC dib_dc = skia::BeginPlatformPaint(canvas);
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero,
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    skia::EndPlatformPaint(canvas);
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    HDC hdc = ::GetDC(hwnd_);
93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    RECT src_rect = rect.ToRECT();
94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    skia::DrawToNativeContext(canvas, hdc, rect.x(), rect.y(), &src_rect);
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ::ReleaseDC(hwnd_, hdc);
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid SoftwareOutputDeviceWin::CopyToPixels(const gfx::Rect& rect,
100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                           void* pixels) {
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(contents_);
102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SkImageInfo info = SkImageInfo::MakeN32Premul(rect.width(), rect.height());
103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  contents_->sk_canvas()->readPixels(
104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      info, pixels, info.minRowBytes(), rect.x(), rect.y());
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
108