forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgl_canvas.cc
148 lines (120 loc) · 4.99 KB
/
gl_canvas.cc
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// 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_canvas.h"
#include "base/logging.h"
#include "remoting/client/gl_helpers.h"
#include "remoting/client/gl_math.h"
namespace {
const int kVertexSize = 2;
const int kVertexCount = 4;
const char kTexCoordToViewVert[] =
// Region of the texture to be used (normally the whole texture).
"varying vec2 v_texCoord;\n"
"attribute vec2 a_texCoord;\n"
// Position to draw the texture on the canvas.
"attribute vec2 a_position;\n"
// Defines the zoom and pan configurations of the canvas.
"uniform mat3 u_transform;\n"
// Size of the view in pixel.
"uniform vec2 u_viewSize;\n"
// This matrix translates normalized texture coordinates
// ([0, 1] starting at upper-left corner) to the view coordinates
// ([-1, 1] starting at the center of the screen).
// Note that the matrix is defined in column-major order.
"const mat3 tex_to_view = mat3(2, 0, 0,\n"
" 0, -2, 0,\n"
" -1, 1, 0);\n"
"void main() {\n"
" v_texCoord = a_texCoord;\n"
// Transforms coordinates related to the canvas to coordinates
// related to the view.
" vec3 trans_position = u_transform * vec3(a_position, 1.0);\n"
// Normalize the position by the size of the view.
" trans_position.xy /= u_viewSize;\n"
// Transforms texture coordinates to view coordinates and adds
// projection component 1.
" gl_Position = vec4(tex_to_view * trans_position, 1.0);\n"
"}";
const char kDrawTexFrag[] =
"precision mediump float;\n"
// Region on the texture to be used (normally the whole texture).
"varying vec2 v_texCoord;\n"
"uniform sampler2D u_texture;\n"
"uniform float u_alpha_multiplier;\n"
"void main() {\n"
" gl_FragColor = texture2D(u_texture, v_texCoord);\n"
" gl_FragColor.a *= u_alpha_multiplier;\n"
"}";
} // namespace
namespace remoting {
GlCanvas::GlCanvas(int gl_version) : gl_version_(gl_version) {
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_);
vertex_shader_ = CompileShader(GL_VERTEX_SHADER, kTexCoordToViewVert);
fragment_shader_ = CompileShader(GL_FRAGMENT_SHADER, kDrawTexFrag);
program_ = CreateProgram(vertex_shader_, fragment_shader_);
glUseProgram(program_);
transform_location_ = glGetUniformLocation(program_, "u_transform");
view_size_location_ = glGetUniformLocation(program_, "u_viewSize");
texture_location_ = glGetUniformLocation(program_, "u_texture");
alpha_multiplier_location_ =
glGetUniformLocation(program_, "u_alpha_multiplier");
position_location_ = glGetAttribLocation(program_, "a_position");
tex_cord_location_ = glGetAttribLocation(program_, "a_texCoord");
glEnableVertexAttribArray(position_location_);
glEnableVertexAttribArray(tex_cord_location_);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
GlCanvas::~GlCanvas() {
DCHECK(thread_checker_.CalledOnValidThread());
glDisable(GL_BLEND);
glDisableVertexAttribArray(tex_cord_location_);
glDisableVertexAttribArray(position_location_);
glDeleteProgram(program_);
glDeleteShader(vertex_shader_);
glDeleteShader(fragment_shader_);
}
void GlCanvas::SetTransformationMatrix(const std::array<float, 9>& matrix) {
DCHECK(thread_checker_.CalledOnValidThread());
std::array<float, 9> transposed_matrix = matrix;
TransposeTransformationMatrix(&transposed_matrix);
glUniformMatrix3fv(transform_location_, 1, GL_FALSE,
transposed_matrix.data());
transformation_set_ = true;
}
void GlCanvas::SetViewSize(int width, int height) {
DCHECK(width > 0 && height > 0);
glViewport(0, 0, width, height);
float view_size[2] {width, height};
glUniform2fv(view_size_location_, 1, view_size);
view_size_set_ = true;
}
void GlCanvas::DrawTexture(int texture_id,
GLuint texture_handle,
GLuint vertex_buffer,
float alpha_multiplier) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!view_size_set_ || !transformation_set_) {
return;
}
glActiveTexture(GL_TEXTURE0 + texture_id);
glBindTexture(GL_TEXTURE_2D, texture_handle);
glUniform1i(texture_location_, texture_id);
glUniform1f(alpha_multiplier_location_, alpha_multiplier);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer(position_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0,
0);
glVertexAttribPointer(tex_cord_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0,
static_cast<float*>(0) + kVertexSize * kVertexCount);
glDrawArrays(GL_TRIANGLE_STRIP, 0, kVertexCount);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
int GlCanvas::GetGlVersion() const {
return gl_version_;
}
int GlCanvas::GetMaxTextureSize() const {
return max_texture_size_;
}
} // namespace remoting