1 /* 2 * Copyright (C) 2011 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 <string> 18 #include <vector> 19 20 #include "jni/jni_shader_program.h" 21 #include "jni/jni_util.h" 22 23 #include "native/base/logging.h" 24 #include "native/core/geometry.h" 25 #include "native/core/gl_env.h" 26 #include "native/core/gl_frame.h" 27 #include "native/core/shader_program.h" 28 #include "native/core/vertex_frame.h" 29 30 using android::filterfw::GLEnv; 31 using android::filterfw::GLFrame; 32 using android::filterfw::Point; 33 using android::filterfw::ProgramVar; 34 using android::filterfw::Quad; 35 using android::filterfw::ShaderProgram; 36 using android::filterfw::VertexFrame; 37 38 jboolean Java_android_filterfw_core_ShaderProgram_allocate(JNIEnv* env, 39 jobject thiz, 40 jobject gl_env, 41 jstring vertex_shader, 42 jstring fragment_shader) { 43 // Get the GLEnv pointer 44 GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env); 45 46 // Create the shader 47 if (!fragment_shader || !gl_env_ptr) 48 return false; 49 else if (!vertex_shader) 50 return ToJBool(WrapObjectInJava(new ShaderProgram( 51 gl_env_ptr, 52 ToCppString(env, fragment_shader)), 53 env, 54 thiz, 55 true)); 56 else 57 return ToJBool(WrapObjectInJava(new ShaderProgram( 58 gl_env_ptr, 59 ToCppString(env, vertex_shader), 60 ToCppString(env, fragment_shader)), 61 env, 62 thiz, 63 true)); 64 } 65 66 jboolean Java_android_filterfw_core_ShaderProgram_deallocate(JNIEnv* env, jobject thiz) { 67 return ToJBool(DeleteNativeObject<ShaderProgram>(env, thiz)); 68 } 69 70 jboolean Java_android_filterfw_core_ShaderProgram_compileAndLink(JNIEnv* env, jobject thiz) { 71 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 72 return program ? ToJBool(program->CompileAndLink()) : JNI_FALSE; 73 } 74 75 jboolean Java_android_filterfw_core_ShaderProgram_setUniformValue(JNIEnv* env, 76 jobject thiz, 77 jstring key, 78 jobject value) { 79 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 80 const Value c_value = ToCValue(env, value); 81 const std::string c_key = ToCppString(env, key); 82 if (c_value.value) { 83 return ToJBool(program && program->SetUniformValue(c_key, c_value)); 84 } else { 85 LOGE("ShaderProgram: Could not convert java object value passed for key '%s'!", c_key.c_str()); 86 return JNI_FALSE; 87 } 88 } 89 90 jobject Java_android_filterfw_core_ShaderProgram_getUniformValue(JNIEnv* env, 91 jobject thiz, 92 jstring key) { 93 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 94 const std::string c_key = ToCppString(env, key); 95 return program ? ToJObject(env, program->GetUniformValue(c_key)) : JNI_NULL; 96 } 97 98 jboolean Java_android_filterfw_core_ShaderProgram_shaderProcess(JNIEnv* env, 99 jobject thiz, 100 jobjectArray inputs, 101 jobject output) { 102 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 103 std::vector<const GLFrame*> input_frames; 104 if (program && inputs && output) { 105 // Get the input frames 106 const int input_count = env->GetArrayLength(inputs); 107 for (int i = 0; i < input_count; ++i) { 108 jobject input = env->GetObjectArrayElement(inputs, i); 109 const GLFrame* input_frame = ConvertFromJava<GLFrame>(env, input); 110 if (!input || !input_frame) { 111 LOGE("ShaderProgram: invalid input frame %d!", i); 112 return JNI_FALSE; 113 } 114 input_frames.push_back(input_frame); 115 } 116 117 // Get the output frame 118 GLFrame* output_frame = ConvertFromJava<GLFrame>(env, output); 119 if (!output_frame) { 120 LOGE("ShaderProgram: no output frame found!"); 121 return JNI_FALSE; 122 } 123 124 // Process the frames! 125 if (!program->Process(input_frames, output_frame)) { 126 LOGE("ShaderProgram: error processing shader!"); 127 return JNI_FALSE; 128 } 129 130 return JNI_TRUE; 131 } 132 return JNI_FALSE; 133 } 134 135 jobject Java_android_filterfw_core_ShaderProgram_nativeCreateIdentity(JNIEnv* env, 136 jclass, 137 jobject gl_env) { 138 GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env); 139 ShaderProgram* program = gl_env_ptr ? ShaderProgram::CreateIdentity(gl_env_ptr) : NULL; 140 return program ? WrapNewObjectInJava(program, env, false) : NULL; 141 } 142 143 jboolean Java_android_filterfw_core_ShaderProgram_setSourceRegion(JNIEnv* env, 144 jobject thiz, 145 jfloat x0, 146 jfloat y0, 147 jfloat x1, 148 jfloat y1, 149 jfloat x2, 150 jfloat y2, 151 jfloat x3, 152 jfloat y3) { 153 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 154 if (program) { 155 program->SetSourceRegion(Quad(Point(x0, y0), Point(x1, y1), Point(x2, y2), Point(x3, y3))); 156 return JNI_TRUE; 157 } 158 return JNI_FALSE; 159 } 160 161 jboolean Java_android_filterfw_core_ShaderProgram_setTargetRegion(JNIEnv* env, 162 jobject thiz, 163 jfloat x0, 164 jfloat y0, 165 jfloat x1, 166 jfloat y1, 167 jfloat x2, 168 jfloat y2, 169 jfloat x3, 170 jfloat y3) { 171 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 172 if (program) { 173 program->SetTargetRegion(Quad(Point(x0, y0), Point(x1, y1), Point(x2, y2), Point(x3, y3))); 174 return JNI_TRUE; 175 } 176 return JNI_FALSE; 177 } 178 179 jboolean Java_android_filterfw_core_ShaderProgram_setShaderClearsOutput(JNIEnv* env, 180 jobject thiz, 181 jboolean clears) { 182 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 183 if (program) { 184 program->SetClearsOutput(ToCppBool(clears)); 185 return JNI_TRUE; 186 } 187 return JNI_FALSE; 188 } 189 190 jboolean Java_android_filterfw_core_ShaderProgram_setShaderBlendEnabled(JNIEnv* env, 191 jobject thiz, 192 jboolean enable) { 193 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 194 if (program) { 195 program->SetBlendEnabled(ToCppBool(enable)); 196 return JNI_TRUE; 197 } 198 return JNI_FALSE; 199 } 200 201 jboolean Java_android_filterfw_core_ShaderProgram_setShaderBlendFunc(JNIEnv* env, 202 jobject thiz, 203 jint sfactor, 204 jint dfactor) { 205 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 206 if (program) { 207 program->SetBlendFunc(sfactor, dfactor); 208 return JNI_TRUE; 209 } 210 return JNI_FALSE; 211 } 212 213 jboolean Java_android_filterfw_core_ShaderProgram_setShaderClearColor(JNIEnv* env, 214 jobject thiz, 215 jfloat r, 216 jfloat g, 217 jfloat b) { 218 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 219 if (program) { 220 program->SetClearColor(r, g, b, 1.0f); 221 return JNI_TRUE; 222 } 223 return JNI_FALSE; 224 } 225 226 jboolean Java_android_filterfw_core_ShaderProgram_setShaderDrawMode(JNIEnv* env, 227 jobject thiz, 228 jint draw_mode) { 229 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 230 if (program) { 231 program->SetDrawMode(draw_mode); 232 return JNI_TRUE; 233 } 234 return JNI_FALSE; 235 } 236 237 jboolean Java_android_filterfw_core_ShaderProgram_setShaderTileCounts(JNIEnv* env, 238 jobject thiz, 239 jint x_count, 240 jint y_count) { 241 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 242 if (program) { 243 program->SetTileCounts(x_count, y_count); 244 return JNI_TRUE; 245 } 246 return JNI_FALSE; 247 } 248 249 jboolean Java_android_filterfw_core_ShaderProgram_setShaderVertexCount(JNIEnv* env, 250 jobject thiz, 251 jint vertex_count) { 252 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 253 if (program) { 254 program->SetVertexCount(vertex_count); 255 return JNI_TRUE; 256 } 257 return JNI_FALSE; 258 } 259 260 jboolean Java_android_filterfw_core_ShaderProgram_beginShaderDrawing(JNIEnv* env, jobject thiz) { 261 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 262 return ToJBool(program && program->BeginDraw()); 263 } 264 265 jboolean Java_android_filterfw_core_ShaderProgram_setShaderAttributeValues( 266 JNIEnv* env, 267 jobject thiz, 268 jstring attr_name, 269 jfloatArray values, 270 jint component_count) { 271 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 272 if (program) { 273 // Get the floats to set 274 jfloat* float_ptr = env->GetFloatArrayElements(values, NULL); 275 const int length = env->GetArrayLength(values); 276 277 // Get the program variable to set 278 const std::string attr_string = ToCppString(env, attr_name); 279 ProgramVar program_var = program->GetAttribute(attr_string); 280 281 // Set the variable 282 if (float_ptr && ShaderProgram::IsVarValid(program_var)) { 283 const bool success = program->SetAttributeValues(program_var, 284 reinterpret_cast<float*>(float_ptr), 285 length, 286 component_count); 287 env->ReleaseFloatArrayElements(values, float_ptr, JNI_ABORT); 288 return ToJBool(success); 289 } 290 } 291 return JNI_FALSE; 292 } 293 294 jboolean Java_android_filterfw_core_ShaderProgram_setShaderAttributeVertexFrame( 295 JNIEnv* env, 296 jobject thiz, 297 jstring attr_name, 298 jobject vertex_frame, 299 jint type, 300 jint component_count, 301 jint stride, 302 jint offset, 303 jboolean normalize) { 304 ShaderProgram* program = ConvertFromJava<ShaderProgram>(env, thiz); 305 if (program) { 306 // Get the vertex frame 307 VertexFrame* v_frame = ConvertFromJava<VertexFrame>(env, vertex_frame); 308 309 // Get the program variable to set 310 const std::string attr_string = ToCppString(env, attr_name); 311 ProgramVar program_var = program->GetAttribute(attr_string); 312 313 // Set the variable 314 if (v_frame && ShaderProgram::IsVarValid(program_var)) { 315 const bool success = program->SetAttributeValues(program_var, 316 v_frame, 317 type, 318 component_count, 319 stride, 320 offset, 321 ToCppBool(normalize)); 322 return ToJBool(success); 323 } 324 } 325 return JNI_FALSE; 326 } 327