Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame^] | 1 | #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 | |
| 16 | namespace android { |
| 17 | namespace dvr { |
| 18 | |
| 19 | class CompositeHmd; |
| 20 | |
| 21 | // Encapsulates the rendering operations to correct for the HMD's lens |
| 22 | // distortion. |
| 23 | class 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_ |