OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/client/plugin/pepper_view.h" | 5 #include "remoting/client/plugin/pepper_view.h" |
6 | 6 |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "ppapi/cpp/graphics_2d.h" | 9 #include "ppapi/cpp/graphics_2d.h" |
10 #include "ppapi/cpp/image_data.h" | 10 #include "ppapi/cpp/image_data.h" |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 backing_store_->stride() * r.y() + kBytesPerPixel * r.x(); | 123 backing_store_->stride() * r.y() + kBytesPerPixel * r.x(); |
124 | 124 |
125 // TODO(hclam): We really should eliminate this memory copy. | 125 // TODO(hclam): We really should eliminate this memory copy. |
126 for (int j = 0; j < r.height(); ++j) { | 126 for (int j = 0; j < r.height(); ++j) { |
127 memcpy(out, in, r.width() * kBytesPerPixel); | 127 memcpy(out, in, r.width() * kBytesPerPixel); |
128 in += kFrameStride; | 128 in += kFrameStride; |
129 out += backing_store_->stride(); | 129 out += backing_store_->stride(); |
130 } | 130 } |
131 | 131 |
132 if (DoScaling()) { | 132 if (DoScaling()) { |
133 gfx::Rect r_scaled = UpdateScaledBackingStore(r); | 133 pp::Rect r_scaled = UpdateScaledBackingStore( |
| 134 pp::Rect(r.x(), r.y(), r.width(), r.height())); |
134 graphics2d_.PaintImageData(*scaled_backing_store_.get(), pp::Point(0, 0), | 135 graphics2d_.PaintImageData(*scaled_backing_store_.get(), pp::Point(0, 0), |
135 pp::Rect(r_scaled.x(), r_scaled.y(), | 136 r_scaled); |
136 r_scaled.width(), r_scaled.height())); | |
137 } else { | 137 } else { |
138 // Pepper Graphics 2D has a strange and badly documented API that the | 138 // Pepper Graphics 2D has a strange and badly documented API that the |
139 // point here is the offset from the source rect. Why? | 139 // point here is the offset from the source rect. Why? |
140 graphics2d_.PaintImageData(*backing_store_.get(), pp::Point(0, 0), | 140 graphics2d_.PaintImageData(*backing_store_.get(), pp::Point(0, 0), |
141 pp::Rect(r.x(), r.y(), r.width(), r.height())); | 141 pp::Rect(r.x(), r.y(), r.width(), r.height())); |
142 } | 142 } |
143 } | 143 } |
144 | 144 |
145 graphics2d_.Flush(TaskToCompletionCallback( | 145 graphics2d_.Flush(TaskToCompletionCallback( |
146 task_factory_.NewRunnableMethod(&PepperView::OnPaintDone, | 146 task_factory_.NewRunnableMethod(&PepperView::OnPaintDone, |
147 base::Time::Now()))); | 147 base::Time::Now()))); |
148 | 148 |
149 TraceContext::tracer()->PrintString("End Paint Frame."); | 149 TraceContext::tracer()->PrintString("End Paint Frame."); |
150 } | 150 } |
151 | 151 |
152 gfx::Rect PepperView::UpdateScaledBackingStore(const gfx::Rect& r) { | 152 pp::Rect PepperView::UpdateScaledBackingStore(const pp::Rect& r) { |
153 const int kBytesPerPixel = GetBytesPerPixel(media::VideoFrame::RGB32); | 153 const int kBytesPerPixel = GetBytesPerPixel(media::VideoFrame::RGB32); |
154 // Find the updated rectangle in the scaled backing store. | 154 // Find the updated rectangle in the scaled backing store. |
155 gfx::Point top_left = ConvertHostToScreen(r.origin()); | 155 pp::Point top_left = ConvertHostToScreen(r.point()); |
156 gfx::Point bottom_right = ConvertHostToScreen(gfx::Point(r.right(), | 156 pp::Point bottom_right = ConvertHostToScreen(pp::Point(r.right(), |
157 r.bottom())); | 157 r.bottom())); |
158 int r_scaled_left = top_left.x(); | 158 int r_scaled_left = top_left.x(); |
159 int r_scaled_right = bottom_right.x(); | 159 int r_scaled_right = bottom_right.x(); |
160 int r_scaled_top = top_left.y(); | 160 int r_scaled_top = top_left.y(); |
161 int r_scaled_bottom = bottom_right.y(); | 161 int r_scaled_bottom = bottom_right.y(); |
162 if (r_scaled_right <= r_scaled_left || r_scaled_bottom <= r_scaled_top) | 162 if (r_scaled_right <= r_scaled_left || r_scaled_bottom <= r_scaled_top) |
163 return gfx::Rect(r_scaled_left, r_scaled_top, 0, 0); | 163 return pp::Rect(r_scaled_left, r_scaled_top, 0, 0); |
164 | 164 |
165 // Allow for the fact that ConvertHostToScreen and ConvertScreenToHost aren't | 165 // Allow for the fact that ConvertHostToScreen and ConvertScreenToHost aren't |
166 // exact inverses. | 166 // exact inverses. |
167 r_scaled_right++; | 167 r_scaled_right++; |
168 r_scaled_bottom++; | 168 r_scaled_bottom++; |
169 | 169 |
170 // Clip the scaled rectangle. | 170 // Clip the scaled rectangle. |
171 r_scaled_left = std::max(r_scaled_left, 0); | 171 r_scaled_left = std::max(r_scaled_left, 0); |
172 r_scaled_left = std::min(r_scaled_left, client_width_); | 172 r_scaled_left = std::min(r_scaled_left, client_width_); |
173 r_scaled_right = std::max(r_scaled_right, 0); | 173 r_scaled_right = std::max(r_scaled_right, 0); |
174 r_scaled_right = std::min(r_scaled_right, client_width_); | 174 r_scaled_right = std::min(r_scaled_right, client_width_); |
175 r_scaled_top = std::max(r_scaled_top, 0); | 175 r_scaled_top = std::max(r_scaled_top, 0); |
176 r_scaled_top = std::min(r_scaled_top, client_height_); | 176 r_scaled_top = std::min(r_scaled_top, client_height_); |
177 r_scaled_bottom = std::max(r_scaled_bottom, 0); | 177 r_scaled_bottom = std::max(r_scaled_bottom, 0); |
178 r_scaled_bottom = std::min(r_scaled_bottom, client_height_); | 178 r_scaled_bottom = std::min(r_scaled_bottom, client_height_); |
179 | 179 |
180 // Blit from the backing store to the scaled backing store. | 180 // Blit from the backing store to the scaled backing store. |
181 for (int y_scaled = r_scaled_top; y_scaled < r_scaled_bottom; y_scaled++) { | 181 for (int y_scaled = r_scaled_top; y_scaled < r_scaled_bottom; y_scaled++) { |
182 int y = ConvertScreenToHost(gfx::Point(0, y_scaled)).y(); | 182 int y = ConvertScreenToHost(pp::Point(0, y_scaled)).y(); |
183 // Special case where each pixel is a word. | 183 // Special case where each pixel is a word. |
184 if ((kBytesPerPixel == 4) && (backing_store_->stride() % 4 == 0) && | 184 if ((kBytesPerPixel == 4) && (backing_store_->stride() % 4 == 0) && |
185 (scaled_backing_store_->stride() % 4 == 0)) { | 185 (scaled_backing_store_->stride() % 4 == 0)) { |
186 uint32* from = reinterpret_cast<uint32*>(backing_store_->data()) + | 186 uint32* from = reinterpret_cast<uint32*>(backing_store_->data()) + |
187 (y * backing_store_->stride() / 4); | 187 (y * backing_store_->stride() / 4); |
188 uint32* to = reinterpret_cast<uint32*>(scaled_backing_store_->data()) + | 188 uint32* to = reinterpret_cast<uint32*>(scaled_backing_store_->data()) + |
189 (y_scaled * scaled_backing_store_->stride() / 4) + r_scaled_left; | 189 (y_scaled * scaled_backing_store_->stride() / 4) + r_scaled_left; |
190 uint32* to_max = to + (r_scaled_right - r_scaled_left); | 190 uint32* to_max = to + (r_scaled_right - r_scaled_left); |
191 const int* offset = &screen_x_to_host_x_[r_scaled_left]; | 191 const int* offset = &screen_x_to_host_x_[r_scaled_left]; |
192 while (to < to_max) | 192 while (to < to_max) |
193 *to++ = from[*offset++]; | 193 *to++ = from[*offset++]; |
194 } else { | 194 } else { |
195 // Currently that special case is the only case that's ever encountered. | 195 // Currently that special case is the only case that's ever encountered. |
196 NOTREACHED(); | 196 NOTREACHED(); |
197 uint8* from = reinterpret_cast<uint8*>(backing_store_->data()) + | 197 uint8* from = reinterpret_cast<uint8*>(backing_store_->data()) + |
198 (y * backing_store_->stride()); | 198 (y * backing_store_->stride()); |
199 uint8* to = reinterpret_cast<uint8*>(scaled_backing_store_->data()) + | 199 uint8* to = reinterpret_cast<uint8*>(scaled_backing_store_->data()) + |
200 (y_scaled * scaled_backing_store_->stride()) + | 200 (y_scaled * scaled_backing_store_->stride()) + |
201 (r_scaled_left * kBytesPerPixel); | 201 (r_scaled_left * kBytesPerPixel); |
202 for (int x_sc = r_scaled_left; x_sc < r_scaled_right; x_sc++) { | 202 for (int x_sc = r_scaled_left; x_sc < r_scaled_right; x_sc++) { |
203 int x = screen_x_to_host_x_[x_sc]; | 203 int x = screen_x_to_host_x_[x_sc]; |
204 memcpy(to, from + (x * kBytesPerPixel), kBytesPerPixel); | 204 memcpy(to, from + (x * kBytesPerPixel), kBytesPerPixel); |
205 to += kBytesPerPixel; | 205 to += kBytesPerPixel; |
206 } | 206 } |
207 } | 207 } |
208 } | 208 } |
209 return gfx::Rect(r_scaled_left, r_scaled_top, r_scaled_right - r_scaled_left, | 209 return pp::Rect(r_scaled_left, r_scaled_top, r_scaled_right - r_scaled_left, |
210 r_scaled_bottom - r_scaled_top); | 210 r_scaled_bottom - r_scaled_top); |
211 } | 211 } |
212 | 212 |
213 void PepperView::BlankRect(pp::ImageData& image_data, const gfx::Rect& rect) { | 213 void PepperView::BlankRect(pp::ImageData& image_data, const pp::Rect& rect) { |
214 const int kBytesPerPixel = GetBytesPerPixel(media::VideoFrame::RGB32); | 214 const int kBytesPerPixel = GetBytesPerPixel(media::VideoFrame::RGB32); |
215 for (int y = rect.y(); y < rect.bottom(); y++) { | 215 for (int y = rect.y(); y < rect.bottom(); y++) { |
216 uint8* to = reinterpret_cast<uint8*>(image_data.data()) + | 216 uint8* to = reinterpret_cast<uint8*>(image_data.data()) + |
217 (y * image_data.stride()) + (rect.x() * kBytesPerPixel); | 217 (y * image_data.stride()) + (rect.x() * kBytesPerPixel); |
218 memset(to, 0xff, rect.width() * kBytesPerPixel); | 218 memset(to, 0xff, rect.width() * kBytesPerPixel); |
219 } | 219 } |
220 } | 220 } |
221 | 221 |
222 void PepperView::SetSolidFill(uint32 color) { | 222 void PepperView::SetSolidFill(uint32 color) { |
223 DCHECK(CurrentlyOnPluginThread()); | 223 DCHECK(CurrentlyOnPluginThread()); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 return; | 278 return; |
279 | 279 |
280 host_width_ = width; | 280 host_width_ = width; |
281 host_height_ = height; | 281 host_height_ = height; |
282 | 282 |
283 ResizeInternals(); | 283 ResizeInternals(); |
284 | 284 |
285 instance_->GetScriptableObject()->SetDesktopSize(host_width_, host_height_); | 285 instance_->GetScriptableObject()->SetDesktopSize(host_width_, host_height_); |
286 } | 286 } |
287 | 287 |
288 gfx::Point PepperView::ConvertScreenToHost(const gfx::Point& p) const { | 288 pp::Point PepperView::ConvertScreenToHost(const pp::Point& p) const { |
289 DCHECK(CurrentlyOnPluginThread()); | 289 DCHECK(CurrentlyOnPluginThread()); |
290 | 290 |
291 int x = static_cast<int>(p.x() / screen_scale_); | 291 int x = static_cast<int>(p.x() / screen_scale_); |
292 x = std::min(x, host_width_ - 1); | 292 x = std::min(x, host_width_ - 1); |
293 x = std::max(x, 0); | 293 x = std::max(x, 0); |
294 int y = static_cast<int>(p.y() / screen_scale_); | 294 int y = static_cast<int>(p.y() / screen_scale_); |
295 y = std::min(y, host_height_ - 1); | 295 y = std::min(y, host_height_ - 1); |
296 y = std::max(y, 0); | 296 y = std::max(y, 0); |
297 return gfx::Point(x, y); | 297 return pp::Point(x, y); |
298 } | 298 } |
299 | 299 |
300 gfx::Point PepperView::ConvertHostToScreen(const gfx::Point& p) const { | 300 pp::Point PepperView::ConvertHostToScreen(const pp::Point& p) const { |
301 return gfx::Point(static_cast<int>(p.x() * screen_scale_), | 301 return pp::Point(static_cast<int>(p.x() * screen_scale_), |
302 static_cast<int>(p.y() * screen_scale_)); | 302 static_cast<int>(p.y() * screen_scale_)); |
303 } | 303 } |
304 | 304 |
305 void PepperView::SetScreenScale(double screen_scale) { | 305 void PepperView::SetScreenScale(double screen_scale) { |
306 if (screen_scale == screen_scale_) | 306 if (screen_scale == screen_scale_) |
307 return; | 307 return; |
308 screen_scale_ = screen_scale; | 308 screen_scale_ = screen_scale; |
309 ResizeInternals(); | 309 ResizeInternals(); |
310 RefreshPaint(); | 310 RefreshPaint(); |
311 } | 311 } |
312 | 312 |
313 void PepperView::RefreshPaint() { | 313 void PepperView::RefreshPaint() { |
314 if (DoScaling()) { | 314 if (DoScaling()) { |
315 // Render from the whole backing store, to the scaled backing store, at the | 315 // Render from the whole backing store, to the scaled backing store, at the |
316 // current scale. | 316 // current scale. |
317 gfx::Rect updated_rect = UpdateScaledBackingStore(gfx::Rect( | 317 pp::Rect updated_rect = UpdateScaledBackingStore(pp::Rect( |
318 host_width_, host_height_)); | 318 host_width_, host_height_)); |
319 // If the scale has just decreased, then there is stale raster data | 319 // If the scale has just decreased, then there is stale raster data |
320 // to the right of, and below, the scaled copy of the host screen that's | 320 // to the right of, and below, the scaled copy of the host screen that's |
321 // just been rendered into the scaled backing store. | 321 // just been rendered into the scaled backing store. |
322 // So blank out everything to the east of that copy... | 322 // So blank out everything to the east of that copy... |
323 BlankRect(*scaled_backing_store_, gfx::Rect( | 323 BlankRect(*scaled_backing_store_, pp::Rect( |
324 updated_rect.right(), 0, | 324 updated_rect.right(), 0, |
325 scaled_backing_store_->size().width() - updated_rect.right(), | 325 scaled_backing_store_->size().width() - updated_rect.right(), |
326 updated_rect.bottom())); | 326 updated_rect.bottom())); |
327 // ...and everything to the south and south-east. | 327 // ...and everything to the south and south-east. |
328 BlankRect(*scaled_backing_store_, gfx::Rect( | 328 BlankRect(*scaled_backing_store_, pp::Rect( |
329 0, updated_rect.bottom(), scaled_backing_store_->size().width(), | 329 0, updated_rect.bottom(), scaled_backing_store_->size().width(), |
330 scaled_backing_store_->size().height() - updated_rect.bottom())); | 330 scaled_backing_store_->size().height() - updated_rect.bottom())); |
331 graphics2d_.PaintImageData(*scaled_backing_store_.get(), pp::Point(0, 0), | 331 graphics2d_.PaintImageData(*scaled_backing_store_.get(), pp::Point(0, 0), |
332 pp::Rect(scaled_backing_store_->size())); | 332 pp::Rect(scaled_backing_store_->size())); |
333 graphics2d_.Flush(TaskToCompletionCallback( | 333 graphics2d_.Flush(TaskToCompletionCallback( |
334 task_factory_.NewRunnableMethod(&PepperView::OnRefreshPaintDone))); | 334 task_factory_.NewRunnableMethod(&PepperView::OnRefreshPaintDone))); |
335 } else { | 335 } else { |
336 graphics2d_.PaintImageData(*backing_store_.get(), pp::Point(0, 0), | 336 graphics2d_.PaintImageData(*backing_store_.get(), pp::Point(0, 0), |
337 pp::Rect(backing_store_->size())); | 337 pp::Rect(backing_store_->size())); |
338 graphics2d_.Flush(TaskToCompletionCallback( | 338 graphics2d_.Flush(TaskToCompletionCallback( |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 << "Not enough memory for scaled backing store."; | 377 << "Not enough memory for scaled backing store."; |
378 } | 378 } |
379 } else { | 379 } else { |
380 scaled_backing_store_.reset(); | 380 scaled_backing_store_.reset(); |
381 } | 381 } |
382 | 382 |
383 // Cache the horizontal component of the map from client screen co-ordinates | 383 // Cache the horizontal component of the map from client screen co-ordinates |
384 // to host screen co-ordinates. | 384 // to host screen co-ordinates. |
385 screen_x_to_host_x_.reset(new int[client_width_]); | 385 screen_x_to_host_x_.reset(new int[client_width_]); |
386 for (int x = 0; x < client_width_; x++) | 386 for (int x = 0; x < client_width_; x++) |
387 screen_x_to_host_x_[x] = ConvertScreenToHost(gfx::Point(x, 0)).x(); | 387 screen_x_to_host_x_[x] = ConvertScreenToHost(pp::Point(x, 0)).x(); |
388 } | 388 } |
389 | 389 |
390 bool PepperView::DoScaling() const { | 390 bool PepperView::DoScaling() const { |
391 return (screen_scale_ != 1.0); | 391 return (screen_scale_ != 1.0); |
392 } | 392 } |
393 | 393 |
394 void PepperView::SetScreenSize(int width, int height) { | 394 void PepperView::SetScreenSize(int width, int height) { |
395 DCHECK(CurrentlyOnPluginThread()); | 395 DCHECK(CurrentlyOnPluginThread()); |
396 | 396 |
397 client_width_ = width; | 397 client_width_ = width; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 instance_->GetStats()->video_paint_ms()->Record( | 467 instance_->GetStats()->video_paint_ms()->Record( |
468 (base::Time::Now() - paint_start).InMilliseconds()); | 468 (base::Time::Now() - paint_start).InMilliseconds()); |
469 return; | 469 return; |
470 } | 470 } |
471 | 471 |
472 void PepperView::OnRefreshPaintDone() { | 472 void PepperView::OnRefreshPaintDone() { |
473 DCHECK(CurrentlyOnPluginThread()); | 473 DCHECK(CurrentlyOnPluginThread()); |
474 } | 474 } |
475 | 475 |
476 } // namespace remoting | 476 } // namespace remoting |
OLD | NEW |