• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 #include "VideoTex.h"
20 #include "glError.h"
21 #include "shader.h"
22 #include "shader_simpleTex.h"
23 
24 #include <aidl/android/hardware/automotive/evs/CameraDesc.h>
25 #include <aidl/android/hardware/automotive/evs/IEvsEnumerator.h>
26 #include <aidl/android/hardware/automotive/evs/Stream.h>
27 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
28 #include <android-base/logging.h>
29 #include <math/mat4.h>
30 #include <system/camera_metadata.h>
31 
32 namespace {
33 
34 using aidl::android::hardware::automotive::evs::BufferDesc;
35 using aidl::android::hardware::automotive::evs::CameraDesc;
36 using aidl::android::hardware::automotive::evs::IEvsEnumerator;
37 using aidl::android::hardware::automotive::evs::Stream;
38 
39 typedef struct {
40     int32_t id;
41     int32_t width;
42     int32_t height;
43     int32_t format;
44     int32_t direction;
45     int32_t framerate;
46 } RawStreamConfig;
47 
48 const size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
49 
50 }  // namespace
51 
RenderDirectView(std::shared_ptr<IEvsEnumerator> enumerator,const CameraDesc & camDesc,const ConfigManager & config)52 RenderDirectView::RenderDirectView(std::shared_ptr<IEvsEnumerator> enumerator,
53                                    const CameraDesc& camDesc, const ConfigManager& config) :
54       mEnumerator(enumerator), mCameraDesc(camDesc), mConfig(config) {
55     // Find and store the target camera configuration
56     const auto& camList = mConfig.getCameras();
57     const auto target = std::find_if(camList.begin(), camList.end(),
58                                      [this](const ConfigManager::CameraInfo& info) {
59                                          return info.cameraId == mCameraDesc.id;
60                                      });
61     if (target != camList.end()) {
62         // Store the info
63         mCameraInfo = *target;
64 
65         // Calculate a rotation matrix
66         float sinRoll, cosRoll;
67         sincosf(mCameraInfo.roll, &sinRoll, &cosRoll);
68         mRotationMat = {cosRoll, -sinRoll, sinRoll, cosRoll};
69     }
70 }
71 
activate()72 bool RenderDirectView::activate() {
73     // Ensure GL is ready to go...
74     if (!prepareGL()) {
75         LOG(ERROR) << "Error initializing GL";
76         return false;
77     }
78 
79     // Load our shader program if we don't have it already
80     if (!mShaderProgram) {
81         mShaderProgram = buildShaderProgram(vtxShader_simpleTexture, pixShader_simpleTexture,
82                                             "simpleTexture");
83         if (!mShaderProgram) {
84             LOG(ERROR) << "Error building shader program";
85             return false;
86         }
87     }
88 
89     bool foundCfg = false;
90     std::unique_ptr<Stream> targetCfg(new Stream());
91 
92     if (!foundCfg) {
93         // This logic picks the first configuration in the list among them that
94         // support RGBA8888 format and its frame rate is faster than minReqFps.
95         const int32_t minReqFps = 15;
96         int32_t maxArea = 0;
97         camera_metadata_entry_t streamCfgs;
98         if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(
99                                                 mCameraDesc.metadata.data()),
100                                         ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
101                                         &streamCfgs)) {
102             // Stream configurations are found in metadata
103             RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
104             for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
105                 if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
106                     ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
107                     if (ptr->framerate >= minReqFps && ptr->width * ptr->height > maxArea) {
108                         targetCfg->id = ptr->id;
109                         targetCfg->width = ptr->width;
110                         targetCfg->height = ptr->height;
111 
112                         maxArea = ptr->width * ptr->height;
113 
114                         foundCfg = true;
115                     }
116                 }
117                 ++ptr;
118             }
119         } else {
120             LOG(WARNING) << "No stream configuration data is found; "
121                          << "default parameters will be used.";
122         }
123     }
124 
125     // This client always wants below input data format
126     targetCfg->format = aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888;
127 
128     // Construct our video texture
129     mTexture.reset(createVideoTexture(mEnumerator, mCameraDesc.id.c_str(),
130                                       foundCfg ? std::move(targetCfg) : nullptr, sDisplay,
131                                       mConfig.getUseExternalMemory(),
132                                       mConfig.getExternalMemoryFormat()));
133     if (!mTexture) {
134         LOG(ERROR) << "Failed to set up video texture for " << mCameraDesc.id;
135         return false;
136     }
137 
138     return true;
139 }
140 
deactivate()141 void RenderDirectView::deactivate() {
142     // Release our video texture
143     // We can't hold onto it because some other Render object might need the same camera
144     mTexture = nullptr;
145 }
146 
drawFrame(const BufferDesc & tgtBuffer)147 bool RenderDirectView::drawFrame(const BufferDesc& tgtBuffer) {
148     // Tell GL to render to the given buffer
149     if (!attachRenderTarget(tgtBuffer)) {
150         LOG(ERROR) << "Failed to attached render target";
151         return false;
152     }
153 
154     // Select our screen space simple texture shader
155     glUseProgram(mShaderProgram);
156 
157     // Set up the model to clip space transform (identity matrix if we're modeling in screen space)
158     android::vec2 leftTop = {-0.5f, 0.5f};
159     android::vec2 rightTop = {0.5f, 0.5f};
160     android::vec2 leftBottom = {-0.5f, -0.5f};
161     android::vec2 rightBottom = {0.5f, -0.5f};
162     GLint loc = glGetUniformLocation(mShaderProgram, "cameraMat");
163     if (loc < 0) {
164         LOG(ERROR) << "Couldn't set shader parameter 'cameraMat'";
165         return false;
166     } else {
167         const android::mat4 identityMatrix;
168         glUniformMatrix4fv(loc, 1, false, identityMatrix.asArray());
169 
170         // Rotate the preview
171         leftTop = mRotationMat * leftTop;
172         leftBottom = mRotationMat * leftBottom;
173         rightTop = mRotationMat * rightTop;
174         rightBottom = mRotationMat * rightBottom;
175     }
176 
177     // Bind the texture and assign it to the shader's sampler
178     mTexture->refresh();
179     glActiveTexture(GL_TEXTURE0);
180     glBindTexture(GL_TEXTURE_2D, mTexture->glId());
181 
182     GLint sampler = glGetUniformLocation(mShaderProgram, "tex");
183     if (sampler < 0) {
184         LOG(ERROR) << "Couldn't set shader parameter 'tex'";
185         return false;
186     } else {
187         // Tell the sampler we looked up from the shader to use texture slot 0 as its source
188         glUniform1i(sampler, 0);
189     }
190 
191     // We want our image to show up opaque regardless of alpha values
192     glDisable(GL_BLEND);
193 
194     // Draw a rectangle on the screen
195     GLfloat vertsCarPos[] = {
196             -1.0, 1.0,  0.0f,  // left top in window space
197             1.0,  1.0,  0.0f,  // right top
198             -1.0, -1.0, 0.0f,  // left bottom
199             1.0,  -1.0, 0.0f   // right bottom
200     };
201 
202     // Flip the preview if needed
203     if (mCameraInfo.hflip) {
204         std::swap(leftTop.x, rightTop.x);
205         std::swap(leftBottom.x, rightBottom.x);
206     }
207 
208     if (mCameraInfo.vflip) {
209         std::swap(leftTop.y, leftBottom.y);
210         std::swap(rightTop.y, rightBottom.y);
211     }
212 
213     GLfloat vertsCarTex[] = {leftTop.x + 0.5f,     leftTop.y + 0.5f,    rightTop.x + 0.5f,
214                              rightTop.y + 0.5f,    leftBottom.x + 0.5f, leftBottom.y + 0.5f,
215                              rightBottom.x + 0.5f, rightBottom.y + 0.5f};
216     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertsCarPos);
217     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, vertsCarTex);
218     glEnableVertexAttribArray(0);
219     glEnableVertexAttribArray(1);
220 
221     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
222 
223     glDisableVertexAttribArray(0);
224     glDisableVertexAttribArray(1);
225 
226     // Now that everything is submitted, release our hold on the texture resource
227     detachRenderTarget();
228 
229     // Wait for the rendering to finish
230     glFinish();
231     detachRenderTarget();
232     return true;
233 }
234