blob: e1c81146084c31d6ed5236e689148350bf4c7b53 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#ifndef ANDROID_DVR_DISTORTION_RENDERER_H_
2#define ANDROID_DVR_DISTORTION_RENDERER_H_
3
4#include <EGL/egl.h>
5#include <GLES2/gl2.h>
6#include <array>
7#include <functional>
8
9#include <private/dvr/eds_mesh.h>
10#include <private/dvr/graphics/shader_program.h>
11#include <private/dvr/late_latch.h>
12#include <private/dvr/lucid_pose_tracker.h>
13#include <private/dvr/render_texture_params.h>
14#include <private/dvr/types.h>
15
16namespace android {
17namespace dvr {
18
19class CompositeHmd;
20
21// Encapsulates the rendering operations to correct for the HMD's lens
22// distortion.
23class DistortionRenderer {
24 public:
25 static constexpr int kMaxLayers = 2;
26 static constexpr int kMaxLatchedLayers = 4;
27
28 static const mat4 kViewportFromClipMatrix;
29 static const mat4 kClipFromViewportMatrix;
30
31 // Creates a distortion renderer for distortion function.
32 //
33 // distortion_function the black-box distortion function to apply.
34 // display_size the resolution of the output of the distortion renderer.
35 // distortion_mesh_resolution the amount of subdivision in the
36 // distortion mesh.
37 DistortionRenderer(const CompositeHmd& hmd, vec2i display_size,
38 int distortion_mesh_resolution,
39 bool flip_texture_horizontally,
40 bool flip_texture_vertically, bool separated_eye_buffers,
41 bool eds_enabled, bool late_latch_enabled);
42 ~DistortionRenderer();
43
44 // Returns the distortion factor array for the distortion function that was
45 // passed in at creation time. The distortion factor array contains the
46 // magnification factor induced by the distortion mesh at every vertex. There
47 // is one entry per vertex, and entries are ordered in row-major major. The
48 // array contains the magnification for both eyes averaged.
49 const std::vector<float>& GetDistortionFactorArray();
50
51 // |render_pose_buffer_object| is the per-texture pose array buffer object.
52 // |render_buffer_index| is the per-texture index into the pose array buffer
53 // object. This selects which pose was rendered into the
54 // corresponding texture.
55 void DoLateLatch(uint32_t target_vsync_count,
56 const uint32_t* render_buffer_index,
57 const GLuint* render_pose_buffer_objects,
58 const bool* vertical_flip, const bool* separate_eye,
59 int num_textures);
60
61 // Convenience method that does no flipping.
62 void DoLateLatch(uint32_t target_vsync_count,
63 const uint32_t* render_buffer_index,
64 const GLuint* render_pose_buffer_objects, int num_textures) {
65 bool flip[kMaxLayers] = {false};
66 bool separate[kMaxLayers] = {separated_eye_buffers_};
67 DoLateLatch(target_vsync_count, render_buffer_index,
68 render_pose_buffer_objects, flip, separate, num_textures);
69 }
70
71 void PrepGlState(EyeType eye);
72 void ResetGlState(int num_textures);
73
74 // Applies distortion correction to the given textures by rendering into the
75 // current output target.
76 //
77 // eye Which eye is being corrected.
78 // texture_ids The OpenGL texture IDs of the texture layers.
79 // texture_sizes Dimensions of the corresponding textures.
80 // vertical_flip Whether to flip each input texture vertically.
81 // separate_eye Whether the correspending texture is a separate texture for
82 // left and right eyes. If false, it is a shared texture with
83 // the left view on the left half and right on the right half.
84 // late_latch_layer Which late latch layer index to use for each texture.
85 // Typically this is just {0, 1} unless blend_with_previous_layer is used.
86 // num_textures Number of textures in texture_ids and texture_sizes.
87 // blend_with_previous_layer If enabled, blend this single layer with the
88 // existing framebuffer contents.
89 void ApplyDistortionCorrectionToTexture(
90 EyeType eye, const GLuint* texture_ids, const bool* vertical_flip,
91 const bool* separate_eye, const int* late_latch_layer, int num_textures,
92 bool blend_with_previous_layer, bool do_gl_state_prep);
93
94 // Convenience method that does no flipping.
95 void ApplyDistortionCorrectionToTexture(EyeType eye,
96 const GLuint* texture_ids,
97 int num_textures) {
98 bool flip[kMaxLayers] = {false};
99 bool separate[kMaxLayers] = {separated_eye_buffers_,
100 separated_eye_buffers_};
101 int latch_layer[kMaxLayers] = {0, 1};
102 ApplyDistortionCorrectionToTexture(eye, texture_ids, flip, separate,
103 latch_layer, num_textures, false, true);
104 }
105
106 // Draw a video quad based on the given video texture by rendering into the
107 // current output target.
108 //
109 // eye Which eye is being corrected.
110 // layer_id Which compositor layer the video mesh should be drawn into.
111 // texture_ids The OpenGL texture IDs of the texture layers.
112 // transform The transformation matrix that transforms the video mesh to its
113 // desired eye space position for the target eye.
114 void DrawVideoQuad(EyeType eye, int layer_id, GLuint texture_id,
115 const mat4& transform);
116
117 // Modifies the size of the output display. This is the number of physical
118 // pixels per dimension covered by the display on the output device. Calling
119 // this method is cheap; it only updates the state table of the two
120 // eye-specific mesh nodes.
121 void SetDisplaySize(vec2i size);
122
123 void SetEdsEnabled(bool enabled);
124 void SetChromaticAberrationCorrectionEnabled(bool enabled) {
125 chromatic_aberration_correction_enabled_ = enabled;
126 }
127 void SetUseAlphaVignette(bool enabled) { use_alpha_vignette_ = enabled; }
128
129 bool GetLastEdsPose(LateLatchOutput* out_data, int layer_id = 0) const;
130
131 private:
132 enum ShaderProgramType {
133 kNoChromaticAberrationCorrection,
134 kNoChromaticAberrationCorrectionTwoLayers,
135 kChromaticAberrationCorrection,
136 kChromaticAberrationCorrectionTwoLayers,
137 kChromaticAberrationCorrectionAlphaVignette,
138 kChromaticAberrationCorrectionAlphaVignetteTwoLayers,
139 kChromaticAberrationCorrectionWithBlend,
140 kSimpleVideoQuad,
141 kNumShaderPrograms,
142 };
143
144 struct EdsShader {
145 EdsShader() {}
146 ~EdsShader() {
147 }
148
149 void load(const char* vertex, const char* fragment, int num_layers,
150 bool use_alpha_vignette, float rotation, bool flip_vertical,
151 bool blend_with_previous_layer);
152 void use() { pgm.Use(); }
153
154 // Update uTexFromEyeMatrix and uEyeFromViewportMatrix by the distortion
155 // renderer with the transform matrix.
156 void SetTexFromEyeTransform(const mat4& transform) {
157 glUniformMatrix4fv(uTexFromEyeMatrix, 1, false, transform.data());
158 }
159
160 void SetEyeFromViewportTransform(const mat4& transform) {
161 glUniformMatrix4fv(uEyeFromViewportMatrix, 1, false, transform.data());
162 }
163
164 ShaderProgram pgm;
165
166 // Texture variables, named to match shader strings for convenience.
167 GLint uProjectionMatrix;
168 GLint uTexFromEyeMatrix;
169 GLint uEyeFromViewportMatrix;
170 GLint uTexXMinMax;
171 };
172
173 void DrawEye(EyeType eye, const GLuint* texture_ids,
174 const bool* vertical_flip, const bool* separate_eye,
175 const int* late_latch_layer, int num_textures,
176 bool blend_with_previous_layer, bool do_gl_state_prep);
177
178 // This function is called when there is an update on Hmd and distortion mesh
179 // vertices and factor array will be updated.
180 void RecomputeDistortion(const CompositeHmd& hmd);
181
182 // Per-eye, per flip, per separate eye mode buffers for setting EDS matrix
183 // when EDS is disabled.
184 GLuint uTexFromRecommendedViewportMatrix[2][2][2];
185
186 // Distortion mesh for the each eye.
187 EdsMesh mesh_node_[2];
188 // VBO (vertex buffer object) for distortion mesh vertices.
189 GLuint mesh_vbo_[2];
190 // VAO (vertex array object) for distortion mesh vertex array data.
191 GLuint mesh_vao_[2];
192 // IBO (index buffer object) for distortion mesh indices.
193 GLuint mesh_ibo_[2];
194
195 EdsShader shaders_[kNumShaderPrograms];
196
197 // Enum to indicate which shader program is being used.
198 ShaderProgramType shader_type_;
199
200 bool eds_enabled_;
201 bool chromatic_aberration_correction_enabled_;
202 bool use_alpha_vignette_;
203
204 // This keeps track of what distortion mesh resolution we are using currently.
205 // When there is an update on Hmd, the distortion mesh vertices/factor array
206 // will be re-computed with the old resolution that is stored here.
207 int distortion_mesh_resolution_;
208
209 // The OpenGL ID of the last texture passed to
210 // ApplyDistortionCorrectionToTexture().
211 GLuint last_distortion_texture_id_;
212
213 // GL texture 2D target for application texture.
214 GLint app_texture_target_;
215
216 // Precomputed matrices for EDS and viewport transforms.
217 mat4 tex_from_eye_matrix_[2][2][2];
218 mat4 eye_from_viewport_matrix_[2];
219
220 // Eye viewport locations.
221 vec2i eye_viewport_origin_[2];
222 vec2i eye_viewport_size_;
223
224 vec2i display_size_;
225
226 std::unique_ptr<LateLatch> late_latch_[kMaxLatchedLayers];
227 bool separated_eye_buffers_;
228};
229
230} // namespace dvr
231} // namespace android
232
233#endif // ANDROID_DVR_DISTORTION_RENDERER_H_