1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/gpu/gpu_view_win.h"
#include "chrome/common/gpu_messages.h"
#include "chrome/gpu/gpu_backing_store_win.h"
#include "chrome/gpu/gpu_thread.h"
namespace {
void DrawBackground(const RECT& dirty_rect, CPaintDC* dc) {
HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
dc->FillRect(&dirty_rect, white_brush);
}
void DrawResizeCorner(const RECT& dirty_rect, HDC dc) {
// TODO(brettw): implement this.
}
} // namespace
GpuViewWin::GpuViewWin(GpuThread* gpu_thread,
HWND parent,
int32 routing_id)
: gpu_thread_(gpu_thread),
routing_id_(routing_id),
parent_(parent) {
gpu_thread_->AddRoute(routing_id_, this);
Create(parent_);
SetWindowText(L"GPU window");
ShowWindow(SW_SHOW);
}
GpuViewWin::~GpuViewWin() {
gpu_thread_->RemoveRoute(routing_id_);
// TODO(brettw) may want to delete any dangling backing stores, or perhaps
// assert if one still exists.
}
void GpuViewWin::OnMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(GpuViewWin, msg)
IPC_MESSAGE_HANDLER(GpuMsg_NewBackingStore, OnNewBackingStore)
IPC_END_MESSAGE_MAP_EX()
}
void GpuViewWin::OnChannelConnected(int32 peer_pid) {
}
void GpuViewWin::OnChannelError() {
// TODO(brettw) do we need to delete ourselves now?
}
void GpuViewWin::DidScrollBackingStoreRect(int dx, int dy,
const gfx::Rect& rect) {
// We need to pass in SW_INVALIDATE to ScrollWindowEx. The documentation on
// MSDN states that it only applies to the HRGN argument, which is wrong.
// Not passing in this flag does not invalidate the region which was scrolled
// from, thus causing painting issues.
RECT clip_rect = rect.ToRECT();
ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE);
}
void GpuViewWin::OnNewBackingStore(int32 routing_id, const gfx::Size& size) {
backing_store_.reset(
new GpuBackingStoreWin(this, gpu_thread_, routing_id, size));
MoveWindow(0, 0, size.width(), size.height(), TRUE);
}
void GpuViewWin::OnPaint(HDC unused_dc) {
// Grab the region to paint before creation of paint_dc since it clears the
// damage region.
ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
GetUpdateRgn(damage_region, FALSE);
CPaintDC paint_dc(m_hWnd);
gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint);
if (damaged_rect.IsEmpty())
return;
if (backing_store_.get()) {
gfx::Rect bitmap_rect(gfx::Point(), backing_store_->size());
// Blit only the damaged regions from the backing store.
DWORD data_size = GetRegionData(damage_region, 0, NULL);
// TODO(brettw) why is the "+1" necessary here? When I remove it, the
// page paints black, but according to the documentation, its not needed.
scoped_array<char> region_data_buf(new char[data_size + 1]);
RGNDATA* region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get());
GetRegionData(damage_region, data_size, region_data);
RECT* region_rects = reinterpret_cast<RECT*>(region_data->Buffer);
for (DWORD i = 0; i < region_data->rdh.nCount; ++i) {
gfx::Rect paint_rect = bitmap_rect.Intersect(gfx::Rect(region_rects[i]));
if (!paint_rect.IsEmpty()) {
DrawResizeCorner(paint_rect.ToRECT(), backing_store_->hdc());
BitBlt(paint_dc.m_hDC,
paint_rect.x(),
paint_rect.y(),
paint_rect.width(),
paint_rect.height(),
backing_store_->hdc(),
paint_rect.x(),
paint_rect.y(),
SRCCOPY);
}
}
// Fill the remaining portion of the damaged_rect with the background
if (damaged_rect.right() > bitmap_rect.right()) {
RECT r;
r.left = std::max(bitmap_rect.right(), damaged_rect.x());
r.right = damaged_rect.right();
r.top = damaged_rect.y();
r.bottom = std::min(bitmap_rect.bottom(), damaged_rect.bottom());
DrawBackground(r, &paint_dc);
}
if (damaged_rect.bottom() > bitmap_rect.bottom()) {
RECT r;
r.left = damaged_rect.x();
r.right = damaged_rect.right();
r.top = std::max(bitmap_rect.bottom(), damaged_rect.y());
r.bottom = damaged_rect.bottom();
DrawBackground(r, &paint_dc);
}
} else {
DrawBackground(paint_dc.m_ps.rcPaint, &paint_dc);
}
}
|