void render_texture_update(struct render *R, RID id, int width, int height, const void *pixels, int slice, int miplevel) { struct texture * tex = (struct texture *)array_ref(&R->texture, id); if (tex == NULL) return; GLenum type; int target; bind_texture(R, tex, slice, &type, &target); if (tex->mipmap) { glTexParameteri( type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); } else { glTexParameteri( type, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); } glTexParameteri( type, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glPixelStorei(GL_UNPACK_ALIGNMENT,1); GLint format = 0; GLenum itype = 0; int compressed = texture_format(tex, &format, &itype); if (compressed) { glCompressedTexImage2D(target, miplevel, format, (GLsizei)tex->width, (GLsizei)tex->height, 0, calc_texture_size(tex->format, width, height), pixels); } else { glTexImage2D(target, miplevel, format, (GLsizei)width, (GLsizei)height, 0, format, itype, pixels); } CHECK_GL_ERROR }
static v8::Handle<v8::Value> validate_arguments( texture_compiler_args_t *args, image::buffer_t *source) { v8::HandleScope scope; bool mipmaps = args->build_mipmaps; size_t channels = source->channel_count; if (TEXTURE_TYPE_UNKNOWN == texture_type(args->texture_type, channels)) { return scope.Close(ex("The type field has an invalid value.")); } if (TEXTURE_FORMAT_UNKNOWN == texture_format(args->target_format, channels)) { return scope.Close(ex("The format field has an invalid value.")); } if (TEXTURE_TARGET_UNKNOWN == texture_target(args->texture_target)) { return scope.Close(ex("The target field has an invalid value.")); } if (TEXTURE_WRAP_UNKNOWN == texture_wrap(args->wrap_mode_s)) { return scope.Close(ex("The wrapModeS field has an invalid value.")); } if (TEXTURE_WRAP_UNKNOWN == texture_wrap(args->wrap_mode_t)) { return scope.Close(ex("The wrapModeT field has an invalid value.")); } if (TEXTURE_FILTER_UNKNOWN == magnify_filter(args->magnify_filter)) { return scope.Close(ex("The magnifyFilter field has an invalid value.")); } if (TEXTURE_FILTER_UNKNOWN == minify_filter(args->minify_filter, mipmaps)) { return scope.Close(ex("The minifyFilter field has an invalid value.")); } return scope.Close(v8::Undefined()); }
void render_texture_subupdate(struct render *R, RID id, const void *pixels, int x, int y, int w, int h) { struct texture * tex = (struct texture *)array_ref(&R->texture, id); if (tex == NULL) return; GLenum type; int target; bind_texture(R, tex, 0, &type, &target); glPixelStorei(GL_UNPACK_ALIGNMENT,1); GLint format = 0; GLenum itype = 0; int compressed = texture_format(tex, &format, &itype); if (compressed) { glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, calc_texture_size(tex->format, w, h), pixels); } else { glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, itype, pixels); } CHECK_GL_ERROR }
static v8::Handle<v8::Object> output_to_v8_object( texture_compiler_args_t *args, texture_compiler_outputs_t *output, v8::Handle<v8::Array> levels) { v8::HandleScope scope; v8::Handle<v8::Object> metadata = v8::Object::New(); v8::Handle<v8::String> prop_type = v8::String::New("type"); v8::Handle<v8::String> prop_wrapS = v8::String::New("wrapS"); v8::Handle<v8::String> prop_wrapT = v8::String::New("wrapT"); v8::Handle<v8::String> prop_levels = v8::String::New("levels"); v8::Handle<v8::String> prop_target = v8::String::New("target"); v8::Handle<v8::String> prop_format = v8::String::New("format"); v8::Handle<v8::String> prop_dataType = v8::String::New("dataType"); v8::Handle<v8::String> prop_magFilter = v8::String::New("magFilter"); v8::Handle<v8::String> prop_minFilter = v8::String::New("minFilter"); v8::Handle<v8::String> prop_hasMipmaps = v8::String::New("hasMipmaps"); char const *type_string = args->texture_type; char const *format_string = args->target_format; char const *target_string = args->texture_target; size_t channels = output->channel_count; bool mipmaps = output->level_count > 1; int32_t format = texture_format(format_string, channels); metadata->Set(prop_type, v8::String::New(args->texture_type)); metadata->Set(prop_target, gl_target_v8(target_string)); metadata->Set(prop_format, gl_format_v8(type_string, format)); metadata->Set(prop_dataType, gl_data_type_v8(format)); metadata->Set(prop_wrapS, v8::String::New(args->wrap_mode_s)); metadata->Set(prop_wrapT, v8::String::New(args->wrap_mode_t)); metadata->Set(prop_magFilter, v8::String::New(args->magnify_filter)); metadata->Set(prop_minFilter, v8::String::New(args->minify_filter)); metadata->Set(prop_hasMipmaps, mipmaps ? v8::True() : v8::False()); metadata->Set(prop_levels, levels); return scope.Close(metadata); }
v8::Handle<v8::Value> Compile(v8::Arguments const &args) { texture_compiler_args_t tcarg; texture_compiler_inputs_t tcinp; texture_compiler_outputs_t tcout; image::buffer_t image; v8::HandleScope scope; v8::Local<v8::Object> params = args[0]->ToObject(); // extract the arguments into something we can work with // without V8; verify that required arguments are present. v8::Handle<v8::Value> r1 = v8_object_to_compiler_args(params, &tcarg); if (!r1->IsUndefined()) { // an exception was thrown. return it. free_compiler_args(&tcarg); return scope.Close(v8::ThrowException(r1)); } // load the image from the specified source file. if (!file_to_buffer(tcarg.source_path, &image)) { free_compiler_args(&tcarg); return scope.Close(ex("Cannot load file specified by sourcePath.")); } // validate the arguments against the image properties. v8::Handle<v8::Value> r2 = validate_arguments(&tcarg, &image); if (!r2->IsUndefined()) { // an exception was thrown. return it. free_buffer(&image); free_compiler_args(&tcarg); return scope.Close(v8::ThrowException(r2)); } // set up the inputs to the texture compiler. texture_compiler_inputs_init(&tcinp); texture_compiler_outputs_init(&tcout); tcinp.input_image = ℑ tcinp.border_mode = border_sample_mode(tcarg.border_mode); tcinp.target_width = tcarg.target_width; tcinp.target_height = tcarg.target_height; tcinp.maximum_levels = tcarg.level_count; tcinp.build_mipmaps = tcarg.build_mipmaps; tcinp.force_pow2 = tcarg.force_pow2; tcinp.premultiply_a = tcarg.premultiplied; tcinp.flip_y = tcarg.flip_y; // build the texture data. if (!compile_texture(&tcinp, &tcout)) { free_compiler_args(&tcarg); return scope.Close(v8::ThrowException(ex(tcout.error_message))); } // write the raw texture data. size_t nlevels = tcout.level_count; size_t channels = tcout.channel_count; int32_t format = texture_format(tcarg.target_format, channels); char const *target = tcarg.target_path; v8::Handle<v8::Array> levels = v8::Array::New((int) nlevels); v8::Handle<v8::Value> r3 = v8_output_raw(target, format, levels, &tcout); if (!r3->IsUndefined()) { texture_compiler_outputs_free(&tcout); free_buffer(&image); free_compiler_args(&tcarg); return scope.Close(v8::ThrowException(r3)); } // build the object to return to JavaScript. v8::Handle<v8::Object> metadata = output_to_v8_object(&tcarg, &tcout, levels); // release resources that are no longer needed. texture_compiler_outputs_free(&tcout); free_buffer(&image); free_compiler_args(&tcarg); return scope.Close(metadata); }