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..e33553bcc2d6bed1a0cf25bf77aaab7bac495768 |
--- /dev/null |
+++ b/remoting/client/gl_cursor_feedback_texture.cc |
@@ -0,0 +1,124 @@ |
+// 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/base/util.h" |
+ |
+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] |
+ [remoting::kBytesPerPixelRGB32] = { |
+ {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}; |
+ |
+} // namespace |
+ |
+namespace remoting { |
+ |
+void LinearInterpolate(const uint8_t* in1, |
+ const uint8_t* in2, |
+ uint8_t* out, |
+ int percentage, |
+ int current_dimension) { |
+ out[current_dimension] = (in1[current_dimension] * (100 - percentage) + |
+ in2[current_dimension] * percentage) / 100; |
+} |
+ |
+void FillColorByRadius(float radius, uint32_t* out) { |
+ int i; |
+ // Find first radius stop that is not smaller than current radius. |
+ for (i = kColorRingsCount - 1; radius < kFeedbackRadiusStops[i] && i >= 0; |
+ i--) { |
+ } |
+ |
+ if (i < 0) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ if (i == kColorRingsCount - 1) { |
+ // Area outside the circle. Just use the outermost color. |
+ *out = *reinterpret_cast<const uint32_t*>(kFeedbackRingColors[i]); |
+ return; |
+ } |
+ |
+ const uint8_t* first_color = kFeedbackRingColors[i]; |
+ const uint8_t* second_color = kFeedbackRingColors[i + 1]; |
+ float first_radius = kFeedbackRadiusStops[i]; |
+ float second_radius = kFeedbackRadiusStops[i + 1]; |
+ |
+ int percentage = |
+ (radius - first_radius) * 100 / (second_radius - first_radius); |
+ uint8_t* byte_out = reinterpret_cast<uint8_t*>(out); |
+ LinearInterpolate(first_color, second_color, byte_out, percentage, 0); |
+ LinearInterpolate(first_color, second_color, byte_out, percentage, 1); |
+ LinearInterpolate(first_color, second_color, byte_out, percentage, 2); |
+ LinearInterpolate(first_color, second_color, byte_out, percentage, 3); |
+} |
+ |
+void FillColorMapping(uint32_t* map) { |
+ for (int x = 0; x < kFeedbackTexturePixelRadius; x++) { |
+ for (int y = 0; y <= x; y++) { |
+ float radius = |
+ sqrt(x * x + y * y) / kFeedbackTexturePixelRadius; |
+ FillColorByRadius(radius, map + x + y * kFeedbackTexturePixelRadius); |
+ } |
+ } |
+} |
+ |
+void FillFeedbackTexture(uint32_t* texture) { |
+ // Color: RGBA8888. Equivalent to the upper part of the forth quadrant. |
+ std::unique_ptr<uint32_t[]> coord_color_map( |
+ new uint32_t[kFeedbackTexturePixelRadius * kFeedbackTexturePixelRadius]); |
Yuwei
2016/07/20 22:56:48
After the change, it takes about 3ms to generate t
|
+ |
+ FillColorMapping(coord_color_map.get()); |
+ |
+ for (int x = 0; x < kFeedbackTexturePixelDiameter; x++) { |
+ for (int y = 0; y < kFeedbackTexturePixelDiameter; y++) { |
+ int mapped_x = abs(x - kFeedbackTexturePixelRadius); |
+ int mapped_y = abs(y - kFeedbackTexturePixelRadius); |
+ if (mapped_x < mapped_y) { |
+ int temp_x = mapped_x; |
+ mapped_x = mapped_y; |
+ mapped_y = temp_x; |
+ } |
+ texture[x + y * kFeedbackTexturePixelDiameter] = |
+ coord_color_map[mapped_x + mapped_y * kFeedbackTexturePixelRadius]; |
+ } |
+ } |
+} |
+ |
+GlCursorFeedbackTexture* GlCursorFeedbackTexture::GetInstance() { |
+ return base::Singleton<GlCursorFeedbackTexture>::get(); |
+} |
+ |
+const uint8_t* GlCursorFeedbackTexture::GetTexture() const { |
+ return reinterpret_cast<uint8_t*>(texture_.get()); |
+} |
+ |
+int GlCursorFeedbackTexture::GetTextureDiameter() const { |
+ return kFeedbackTexturePixelDiameter; |
+} |
+ |
+GlCursorFeedbackTexture::GlCursorFeedbackTexture() : |
+ texture_(new uint32_t[kFeedbackTexturePixelDiameter * |
+ kFeedbackTexturePixelDiameter]) { |
+ FillFeedbackTexture(texture_.get()); |
+} |
+ |
+GlCursorFeedbackTexture::~GlCursorFeedbackTexture() { |
+} |
+ |
+} // namespace remoting |