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