xref: /aosp_15_r20/external/cronet/third_party/quic_trace/src/tools/render/trace_renderer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "tools/render/trace_renderer.h"
16 
17 #include "tools/render/layout_constants.h"
18 
19 namespace quic_trace {
20 namespace render {
21 
22 namespace {
23 
24 // Passthrough vector shader.
25 const char* kVertexShader = R"(
26 in vec4 coord;
27 void main(void) {
28   gl_Position = vec4(coord);
29 }
30 )";
31 
32 // The geometry shader that accepts a packet represented as a 4-tuple of format
33 // (time, offset, size, kind) and represents it as a square, assigning
34 // appropriate color in process.
35 const char* kGeometryShader = R"(
36 uniform float distance_scale;
37 uniform vec2 margin;
38 uniform int highlighted_packet;
39 
40 const float kSentPacketDurationMs = 1000;
41 const vec4 kUnit = vec4(1,1,1,1);
42 
43 out vec4 v_color;
44 
45 layout(points) in;
46 layout(triangle_strip, max_vertices = 4) out;
47 
48 vec2 norm(vec2 x) {
49   return x * 2 - vec2(1, 1);
50 }
51 
52 vec4 mapPoint(float x, float y) {
53   vec2 point = vec2(x, y);
54   point = norm((point - program_state.offset) / program_state.viewport);
55   return vec4(point * margin, 0, 1);
56 }
57 
58 void main(void) {
59   float time = gl_in[0].gl_Position[0];
60   float offset = gl_in[0].gl_Position[1];
61   float size = gl_in[0].gl_Position[2];
62   float kind = gl_in[0].gl_Position[3];
63 
64   // Sent is blue.
65   v_color = vec4(0.0, 0.0, 0.6, 1.0);
66   // Ack is green.
67   if (kind <= -1) {
68     v_color = vec4(0.0, 0.6, 0.0, 1.0);
69   }
70   // Lost is red.
71   if (kind <= -2) {
72     v_color = vec4(0.8, 0.0, 0.0, 1.0);
73   }
74   // App-limited is orange.
75   if (kind <= -3) {
76     v_color = vec4(1.0, 0.425, 0.0, 1.0);
77   }
78   // Highlight the specified packet by making it brighter.
79   if (highlighted_packet == gl_PrimitiveIDIn) {
80     v_color = kUnit - (kUnit - v_color) * 0.3;
81   }
82 
83   float duration = distance_scale * kSentPacketDurationMs;
84   size *= distance_scale;
85 
86   gl_Position = mapPoint(time, offset);
87   EmitVertex();
88 
89   gl_Position = mapPoint(time + duration, offset);
90   EmitVertex();
91 
92   gl_Position = mapPoint(time, offset + size);
93   EmitVertex();
94 
95   gl_Position = mapPoint(time + duration, offset + size);
96   EmitVertex();
97 
98   EndPrimitive();
99 }
100 )";
101 
102 // A passthrough fragment shader.
103 const char* kFragmentShader = R"(
104 in vec4 v_color;
105 out vec4 color;
106 void main(void) {
107   color = v_color;
108 }
109 )";
110 
PacketTypeToFloat(PacketType type)111 float PacketTypeToFloat(PacketType type) {
112   switch (type) {
113     case PacketType::SENT:
114       return 0;
115     case PacketType::ACKED:
116       return -1;
117     case PacketType::LOST:
118       return -2;
119     case PacketType::APP_LIMITED:
120       return -3;
121   }
122 }
123 }  // namespace
124 
TraceRenderer(const ProgramState * state)125 TraceRenderer::TraceRenderer(const ProgramState* state)
126     : state_(state), shader_(kVertexShader, kGeometryShader, kFragmentShader) {}
127 
PacketCountHint(size_t count)128 void TraceRenderer::PacketCountHint(size_t count) {
129   DCHECK(!buffer_ready_);
130   packet_buffer_.reserve(count);
131 }
132 
AddPacket(uint64_t time,uint64_t offset,uint64_t size,PacketType type)133 void TraceRenderer::AddPacket(uint64_t time,
134                               uint64_t offset,
135                               uint64_t size,
136                               PacketType type) {
137   DCHECK(!buffer_ready_);
138   packet_buffer_.push_back(
139       Packet{static_cast<float>(time), static_cast<float>(offset),
140              static_cast<float>(size), PacketTypeToFloat(type)});
141   max_x_ = std::max(max_x_, time + kSentPacketDurationMs);
142   max_y_ = std::max(max_y_, static_cast<float>(offset + size));
143 }
144 
FinishPackets()145 void TraceRenderer::FinishPackets() {
146   glBindBuffer(GL_ARRAY_BUFFER, *buffer_);
147   glBufferData(GL_ARRAY_BUFFER,
148                sizeof(*packet_buffer_.data()) * packet_buffer_.size(),
149                packet_buffer_.data(), GL_STATIC_DRAW);
150 
151   packet_count_ = packet_buffer_.size();
152   packet_buffer_.clear();
153   buffer_ready_ = true;
154 }
155 
Render()156 void TraceRenderer::Render() {
157   DCHECK(buffer_ready_);
158   glUseProgram(*shader_);
159   glBindVertexArray(*array_);
160   glBindBuffer(GL_ARRAY_BUFFER, *buffer_);
161 
162   // Distance scaling.
163   // When packets are sufficiently far, they might get smaller than one pixel;
164   // that makes rendering look noisy and useless.  Scale them back to ensure
165   // they take up at least a pixel on X axis.  Note that we're actually scaling
166   // to 1.1 pixels in order to avoid jitter caused by edge cases when zooming.
167   float distance_scale = 1.f;
168   float packet_size_in_pixels =
169       kSentPacketDurationMs / state_->viewport().x * state_->window().x;
170   if (packet_size_in_pixels < 1.1f) {
171     distance_scale = 1.1f / packet_size_in_pixels;
172   }
173 
174   const vec2 margin = TraceMargin(state_->dpi_scale());
175   const vec2 margin_scale = vec2(1.f, 1.f) - 2 * margin / state_->window();
176   state_->Bind(shader_);
177   shader_.SetUniform("distance_scale", distance_scale);
178   shader_.SetUniform("margin", margin_scale.x, margin_scale.y);
179   shader_.SetUniform("highlighted_packet", highlighted_packet_);
180 
181   GlVertexArrayAttrib coord(shader_, "coord");
182   glVertexAttribPointer(*coord, 4, GL_FLOAT, GL_FALSE, 0, 0);
183 
184   const vec2 render_size = state_->window() - 2 * margin;
185   glEnable(GL_SCISSOR_TEST);
186   glScissor(margin.x, margin.y, render_size.x, render_size.y);
187   glDrawArrays(GL_POINTS, 0, packet_count_);
188   glDisable(GL_SCISSOR_TEST);
189 }
190 
191 }  // namespace render
192 }  // namespace quic_trace
193