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
RenderDirectView(sp<IEvsEnumerator> enumerator,const CameraDesc & camDesc,const ConfigManager & config)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
activate()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
deactivate()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
drawFrame(const BufferDesc & tgtBuffer)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