ssf_fresnel.c (3515B)
1 /* Copyright (C) 2016-2018, 2021-2025 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #include "ssf_fresnel_c.h" 17 18 #include <rsys/math.h> 19 #include <rsys/mem_allocator.h> 20 21 #include <string.h> 22 23 /******************************************************************************* 24 * Helper functions 25 ******************************************************************************/ 26 static INLINE int 27 check_fresnel_type(const struct ssf_fresnel_type* type) 28 { 29 return type 30 && type->eval 31 && IS_POW2(type->alignof_fresnel); 32 } 33 34 static void 35 fresnel_release(ref_T* ref) 36 { 37 struct ssf_fresnel* fresnel = CONTAINER_OF(ref, struct ssf_fresnel, ref); 38 ASSERT(ref); 39 if(fresnel->data) { 40 if(fresnel->type.release) fresnel->type.release(fresnel->data); 41 MEM_RM(fresnel->allocator, fresnel->data); 42 } 43 MEM_RM(fresnel->allocator, fresnel); 44 } 45 46 /******************************************************************************* 47 * Exported functions 48 ******************************************************************************/ 49 res_T 50 ssf_fresnel_create 51 (struct mem_allocator* allocator, 52 const struct ssf_fresnel_type* type, 53 struct ssf_fresnel** out_fresnel) 54 { 55 struct mem_allocator* mem_allocator; 56 struct ssf_fresnel* fresnel = NULL; 57 res_T res = RES_OK; 58 59 if(!out_fresnel || !check_fresnel_type(type)) { 60 res = RES_BAD_ARG; 61 goto error; 62 } 63 64 mem_allocator = allocator ? allocator : &mem_default_allocator; 65 fresnel = MEM_CALLOC(mem_allocator, 1, sizeof(struct ssf_fresnel)); 66 if(!fresnel) { 67 res = RES_MEM_ERR; 68 goto error; 69 } 70 ref_init(&fresnel->ref); 71 fresnel->allocator = mem_allocator; 72 fresnel->type = *type; 73 74 if(fresnel->type.sizeof_fresnel) { 75 fresnel->data = MEM_ALLOC_ALIGNED(fresnel->allocator, 76 fresnel->type.sizeof_fresnel, fresnel->type.alignof_fresnel); 77 if(!fresnel->data) { 78 res = RES_MEM_ERR; 79 goto error; 80 } 81 memset(fresnel->data, 0, fresnel->type.sizeof_fresnel); 82 if(fresnel->type.init) { 83 res = fresnel->type.init(fresnel->allocator, fresnel->data); 84 if(res != RES_OK) goto error; 85 } 86 } 87 88 exit: 89 if(out_fresnel) *out_fresnel = fresnel; 90 return res; 91 error: 92 if(fresnel) { 93 SSF(fresnel_ref_put(fresnel)); 94 fresnel = NULL; 95 } 96 goto exit; 97 } 98 99 res_T 100 ssf_fresnel_ref_get(struct ssf_fresnel* fresnel) 101 { 102 if(!fresnel) return RES_BAD_ARG; 103 ref_get(&fresnel->ref); 104 return RES_OK; 105 } 106 107 res_T 108 ssf_fresnel_ref_put(struct ssf_fresnel* fresnel) 109 { 110 if(!fresnel) return RES_BAD_ARG; 111 ref_put(&fresnel->ref, fresnel_release); 112 return RES_OK; 113 } 114 115 double 116 ssf_fresnel_eval(struct ssf_fresnel* fresnel, const double cos_theta) 117 { 118 ASSERT(fresnel && cos_theta >= 0); 119 return fresnel->type.eval(fresnel->data, cos_theta); 120 } 121 122 res_T 123 ssf_fresnel_get_data(struct ssf_fresnel* fresnel, void** data) 124 { 125 if(!fresnel || !data) return RES_BAD_ARG; 126 *data = fresnel->data; 127 return RES_OK; 128 } 129