1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "RenderDirectView.h" 18 #include "VideoTex.h" 19 #include "glError.h" 20 #include "shader.h" 21 #include "shader_simpleTex.h" 22 23 #include <math/mat4.h> 24 #include <system/camera_metadata.h> 25 #include <android/hardware/camera/device/3.2/ICameraDevice.h> 26 #include <android-base/logging.h> 27 28 using ::android::hardware::camera::device::V3_2::Stream; 29 using ::android::hardware::graphics::common::V1_0::PixelFormat; 30 31 32 typedef struct { 33 int32_t id; 34 int32_t width; 35 int32_t height; 36 int32_t format; 37 int32_t direction; 38 int32_t framerate; 39 } RawStreamConfig; 40 41 const size_t kStreamCfgSz = sizeof(RawStreamConfig); 42 43 44 RenderDirectView::RenderDirectView(sp<IEvsEnumerator> enumerator, 45 const CameraDesc& camDesc, 46 const ConfigManager& config) : 47 mEnumerator(enumerator), 48 mCameraDesc(camDesc), 49 mConfig(config) { 50 /* Nothing to do */ 51 } 52 53 54 bool RenderDirectView::activate() { 55 // Ensure GL is ready to go... 56 if (!prepareGL()) { 57 LOG(ERROR) << "Error initializing GL"; 58 return false; 59 } 60 61 // Load our shader program if we don't have it already 62 if (!mShaderProgram) { 63 mShaderProgram = buildShaderProgram(vtxShader_simpleTexture, 64 pixShader_simpleTexture, 65 "simpleTexture"); 66 if (!mShaderProgram) { 67 LOG(ERROR) << "Error building shader program"; 68 return false; 69 } 70 } 71 72 bool foundCfg = false; 73 std::unique_ptr<Stream> targetCfg(new Stream()); 74 75 if (!foundCfg) { 76 // This logic picks the first configuration in the list among them that 77 // support RGBA8888 format and its frame rate is faster than minReqFps. 78 const int32_t minReqFps = 15; 79 int32_t maxArea = 0; 80 camera_metadata_entry_t streamCfgs; 81 if (!find_camera_metadata_entry( 82 reinterpret_cast<camera_metadata_t *>(mCameraDesc.metadata.data()), 83 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, 84 &streamCfgs)) { 85 // Stream configurations are found in metadata 86 RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32); 87 for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) { 88 if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT && 89 ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) { 90 91 if (ptr->framerate >= minReqFps && 92 ptr->width * ptr->height > maxArea) { 93 targetCfg->id = ptr->id; 94 targetCfg->width = ptr->width; 95 targetCfg->height = ptr->height; 96 97 maxArea = ptr->width * ptr->height; 98 99 foundCfg = true; 100 } 101 } 102 ++ptr; 103 } 104 } else { 105 LOG(WARNING) << "No stream configuration data is found; " 106 << "default parameters will be used."; 107 } 108 } 109 110 // This client always wants below input data format 111 targetCfg->format = 112 static_cast<PixelFormat>(HAL_PIXEL_FORMAT_RGBA_8888); 113 114 // Construct our video texture 115 mTexture.reset(createVideoTexture(mEnumerator, 116 mCameraDesc.v1.cameraId.c_str(), 117 foundCfg ? std::move(targetCfg) : nullptr, 118 sDisplay, 119 mConfig.getUseExternalMemory(), 120 mConfig.getExternalMemoryFormat())); 121 if (!mTexture) { 122 LOG(ERROR) << "Failed to set up video texture for " << mCameraDesc.v1.cameraId; 123 // TODO: For production use, we may actually want to fail in this case, but not yet... 124 // return false; 125 } 126 127 return true; 128 } 129 130 131 void RenderDirectView::deactivate() { 132 // Release our video texture 133 // We can't hold onto it because some other Render object might need the same camera 134 // TODO(b/131492626): investigate whether sharing video textures can save 135 // the time. 136 mTexture = nullptr; 137 } 138 139 140 bool RenderDirectView::drawFrame(const BufferDesc& tgtBuffer) { 141 // Tell GL to render to the given buffer 142 if (!attachRenderTarget(tgtBuffer)) { 143 LOG(ERROR) << "Failed to attached render target"; 144 return false; 145 } 146 147 // Select our screen space simple texture shader 148 glUseProgram(mShaderProgram); 149 150 // Set up the model to clip space transform (identity matrix if we're modeling in screen space) 151 GLint loc = glGetUniformLocation(mShaderProgram, "cameraMat"); 152 if (loc < 0) { 153 LOG(ERROR) << "Couldn't set shader parameter 'cameraMat'"; 154 return false; 155 } else { 156 const android::mat4 identityMatrix; 157 glUniformMatrix4fv(loc, 1, false, identityMatrix.asArray()); 158 } 159 160 161 // Bind the texture and assign it to the shader's sampler 162 mTexture->refresh(); 163 glActiveTexture(GL_TEXTURE0); 164 glBindTexture(GL_TEXTURE_2D, mTexture->glId()); 165 166 167 GLint sampler = glGetUniformLocation(mShaderProgram, "tex"); 168 if (sampler < 0) { 169 LOG(ERROR) << "Couldn't set shader parameter 'tex'"; 170 return false; 171 } else { 172 // Tell the sampler we looked up from the shader to use texture slot 0 as its source 173 glUniform1i(sampler, 0); 174 } 175 176 // We want our image to show up opaque regardless of alpha values 177 glDisable(GL_BLEND); 178 179 180 // Draw a rectangle on the screen 181 GLfloat vertsCarPos[] = { -1.0, 1.0, 0.0f, // left top in window space 182 1.0, 1.0, 0.0f, // right top 183 -1.0, -1.0, 0.0f, // left bottom 184 1.0, -1.0, 0.0f // right bottom 185 }; 186 // TODO: We're flipping horizontally here, but should do it only for specified cameras! 187 GLfloat vertsCarTex[] = { 1.0f, 1.0f, // left top 188 0.0f, 1.0f, // right top 189 1.0f, 0.0f, // left bottom 190 0.0f, 0.0f // right bottom 191 }; 192 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertsCarPos); 193 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vertsCarTex); 194 glEnableVertexAttribArray(0); 195 glEnableVertexAttribArray(1); 196 197 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 198 199 glDisableVertexAttribArray(0); 200 glDisableVertexAttribArray(1); 201 202 203 // Now that everything is submitted, release our hold on the texture resource 204 detachRenderTarget(); 205 206 // Wait for the rendering to finish 207 glFinish(); 208 detachRenderTarget(); 209 return true; 210 } 211