Index: remoting/client/gl_cursor_feedback_texture.cc |
diff --git a/remoting/client/gl_cursor_feedback_texture.cc b/remoting/client/gl_cursor_feedback_texture.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bd6f0b8a41d55ce4e1700bac954edd13fc25a073 |
--- /dev/null |
+++ b/remoting/client/gl_cursor_feedback_texture.cc |
@@ -0,0 +1,106 @@ |
+// Copyright 2016 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 "remoting/client/gl_cursor_feedback_texture.h" |
+ |
+#include "remoting/client/gl_render_layer.h" |
+ |
+namespace remoting { |
+ |
+namespace { |
+ |
+const int kColorRingsCount = 4; |
+const int kFeedbackTexturePixelDiameter = 512; |
+const int kFeedbackTexturePixelRadius = kFeedbackTexturePixelDiameter / 2; |
+ |
+// RGBA8888 colors. From inside to outside. |
+const uint8_t kFeedbackRingColors[kColorRingsCount] |
+ [GlRenderLayer::kBytesPerPixel] = { |
+ {0, 0, 0, 0}, // transparent black |
+ {0xff, 0xff, 0xff, 0xff}, // white |
+ {0, 0, 0, 0xff}, // black |
+ {0, 0, 0, 0} // transparent black |
+}; |
+ |
+const float kFeedbackRadiusStops[kColorRingsCount] = {0.0f, 0.8f, 0.9f, 1.0f}; |
+ |
+uint32_t GetColorByRadius(float radius) { |
+ int ring_index = kColorRingsCount - 1; |
+ // Find first radius stop that is not smaller than current radius. |
+ while (radius < kFeedbackRadiusStops[ring_index] && ring_index >= 0) { |
+ ring_index--; |
+ } |
+ |
+ if (ring_index < 0) { |
+ NOTREACHED(); |
+ return -1; |
+ } |
+ |
+ if (ring_index == kColorRingsCount - 1) { |
+ // Area outside the circle. Just use the outermost color. |
+ return *reinterpret_cast<const uint32_t*>(kFeedbackRingColors[ring_index]); |
+ } |
+ |
+ const uint8_t* first_color = kFeedbackRingColors[ring_index]; |
+ const uint8_t* second_color = kFeedbackRingColors[ring_index + 1]; |
+ float first_radius = kFeedbackRadiusStops[ring_index]; |
+ float second_radius = kFeedbackRadiusStops[ring_index + 1]; |
+ |
+ uint8_t progress = |
+ (radius - first_radius) * 256 / (second_radius - first_radius); |
+ uint32_t color; |
+ uint8_t* color_ptr = reinterpret_cast<uint8_t*>(&color); |
+ for (int i = 0; i < GlRenderLayer::kBytesPerPixel; i++) { |
+ color_ptr[i] = |
+ (first_color[i] * (256 - progress) + second_color[i] * progress) / 256; |
+ } |
+ return color; |
+} |
+ |
+void FillFeedbackTexture(uint32_t* texture) { |
+ for (int x = 0; x < kFeedbackTexturePixelRadius; x++) { |
+ for (int y = 0; y <= x; y++) { |
+ float radius = sqrt(x * x + y * y) / kFeedbackTexturePixelRadius; |
+ uint32_t color = GetColorByRadius(radius); |
+ |
+ int x1 = kFeedbackTexturePixelRadius + x; |
+ int x2 = kFeedbackTexturePixelRadius - 1 - x; |
+ |
+ int y1 = kFeedbackTexturePixelRadius + y; |
+ int y2 = kFeedbackTexturePixelRadius - 1 - y; |
+ |
+ texture[x1 + y1 * kFeedbackTexturePixelDiameter] = color; |
+ texture[x1 + y2 * kFeedbackTexturePixelDiameter] = color; |
+ texture[x2 + y1 * kFeedbackTexturePixelDiameter] = color; |
+ texture[x2 + y2 * kFeedbackTexturePixelDiameter] = color; |
+ texture[y1 + x1 * kFeedbackTexturePixelDiameter] = color; |
+ texture[y1 + x2 * kFeedbackTexturePixelDiameter] = color; |
+ texture[y2 + x1 * kFeedbackTexturePixelDiameter] = color; |
+ texture[y2 + x2 * kFeedbackTexturePixelDiameter] = color; |
+ } |
+ } |
+} |
+ |
+} // namespace |
+ |
+GlCursorFeedbackTexture* GlCursorFeedbackTexture::GetInstance() { |
+ return base::Singleton<GlCursorFeedbackTexture>::get(); |
+} |
+ |
+const std::vector<uint8_t>& GlCursorFeedbackTexture::GetTexture() const { |
+ return texture_; |
+} |
+ |
+GlCursorFeedbackTexture::GlCursorFeedbackTexture() { |
+ texture_.resize(kTextureWidth * kTextureWidth * |
+ GlRenderLayer::kBytesPerPixel); |
+ FillFeedbackTexture(reinterpret_cast<uint32_t*>(texture_.data())); |
+} |
+ |
+GlCursorFeedbackTexture::~GlCursorFeedbackTexture() {} |
+ |
+const int GlCursorFeedbackTexture::kTextureWidth = |
Sergey Ulanov
2016/07/21 21:55:31
move this above GetInstance()
|
+ kFeedbackTexturePixelDiameter; |
+ |
+} // namespace remoting |