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