1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can 5 * be found in the LICENSE file. 6 * 7 */ 8 9 // 10 // 11 // 12 13 #include <stdlib.h> 14 #include <memory.h> 15 #include <float.h> 16 17 #include "raster_builder.h" 18 19 #include "context.h" 20 #include "weakref.h" 21 22 #include "scheduler.h" 23 #include "handle.h" 24 25 #include "common.h" 26 27 // 28 // 29 // 30 31 #ifndef NDEBUG 32 33 #include <stdio.h> 34 35 #define SKC_CONTEXT_WAIT_DEBUG(p) \ 36 fprintf(stderr,"WAITING ON: " p "\n") 37 38 #else 39 40 #define SKC_CONTEXT_WAIT_DEBUG(p) 41 42 #endif 43 44 // 45 // 46 // 47 48 #define SKC_CONTEXT_WAIT_WHILE(c,p) \ 49 while (p) { \ 50 SKC_CONTEXT_WAIT_DEBUG(#p); \ 51 skc_context_wait(c); \ 52 } 53 54 // 55 // 56 // 57 58 #if 0 59 60 // 61 // IDENTITY TRANSFORM 62 // 63 64 static 65 float const skc_transform_identity[8] = 66 { 67 1.0f, 0.0f, 0.0f, // sx shx tx 68 0.0f, 1.0f, 0.0f, // shy sy ty 69 0.0f, 0.0f // w0 w1 1 <-- always 1 70 }; 71 72 // float const * const skc_transform_identity_ptr = skc_transform_identity; 73 74 // 75 // DEFAULT RASTER CLIP 76 // 77 78 static 79 float const skc_raster_clip_default[4] = 80 { 81 -FLT_MAX, -FLT_MAX, // lower left corner of bounding box 82 +FLT_MAX, +FLT_MAX // upper right corner of bounding box 83 }; 84 85 // float const * const skc_raster_clip_default_ptr = skc_raster_clip_default; 86 87 #endif 88 89 // 90 // 91 // 92 93 skc_err 94 skc_raster_builder_retain(skc_raster_builder_t raster_builder) 95 { 96 raster_builder->refcount += 1; 97 98 return SKC_ERR_SUCCESS; 99 } 100 101 //xbli 102 // 103 // 104 105 skc_err 106 skc_raster_builder_release(skc_raster_builder_t raster_builder) 107 { 108 SKC_ASSERT_STATE_ASSERT(SKC_RASTER_BUILDER_STATE_READY,raster_builder); 109 110 raster_builder->release(raster_builder->impl); 111 112 return SKC_ERR_SUCCESS; 113 } 114 115 // 116 // 117 // 118 119 static 120 skc_bool 121 skc_raster_builder_path_ids_append(struct skc_raster_builder * const raster_builder, 122 union skc_cmd_fill * const cmd, 123 skc_path_t const path) 124 { 125 SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->path_ids.ring)); 126 127 cmd->path = path; 128 129 raster_builder->path_ids.extent[skc_extent_ring_wip_index_inc(&raster_builder->path_ids.ring)] = path; 130 131 return skc_extent_ring_wip_is_full(&raster_builder->path_ids.ring); 132 } 133 134 static 135 skc_bool 136 skc_raster_builder_transforms_append(struct skc_raster_builder * const raster_builder, 137 union skc_cmd_fill * const cmd, 138 skc_transform_weakref_t * const transform_weakref, 139 skc_float const * const transform) 140 { 141 // 142 // FIXME -- check weakref 143 // 144 SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->transforms.ring)); 145 146 cmd->transform = skc_extent_ring_wip_count(&raster_builder->transforms.ring); 147 148 skc_uint const base = skc_extent_ring_wip_index_inc(&raster_builder->transforms.ring); 149 150 memcpy(raster_builder->transforms.extent[base].f32a8,transform,sizeof(skc_float8)); 151 152 return skc_extent_ring_wip_is_full(&raster_builder->transforms.ring); 153 } 154 155 static 156 skc_bool 157 skc_raster_builder_clips_append(struct skc_raster_builder * const raster_builder, 158 union skc_cmd_fill * const cmd, 159 skc_raster_clip_weakref_t * const raster_clip_weakref, 160 skc_float const * const raster_clip) 161 { 162 // 163 // FIXME -- check weakref 164 // 165 SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->clips.ring)); 166 167 cmd->clip = skc_extent_ring_wip_count(&raster_builder->clips.ring); 168 169 skc_uint const base = skc_extent_ring_wip_index_inc(&raster_builder->clips.ring); 170 171 memcpy(raster_builder->clips.extent[base].f32a4,raster_clip,sizeof(skc_float4)); 172 173 return skc_extent_ring_wip_is_full(&raster_builder->clips.ring); 174 } 175 176 static 177 skc_bool 178 skc_raster_builder_cmds_append(struct skc_raster_builder * const raster_builder, 179 union skc_cmd_fill * const cmd) 180 { 181 SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->fill_cmds.ring)); 182 183 cmd->cohort = skc_extent_ring_wip_count(&raster_builder->raster_ids.ring); 184 185 skc_uint const base = skc_extent_ring_wip_index_inc(&raster_builder->fill_cmds.ring); 186 187 raster_builder->fill_cmds.extent[base] = *cmd; 188 189 #if 0 190 fprintf(stderr,"[ %4u, %4u, %4u, %4u ]\n", 191 cmd->path, 192 cmd->transform, 193 cmd->clip, 194 cmd->cohort); 195 #endif 196 197 return skc_extent_ring_wip_is_full(&raster_builder->fill_cmds.ring); 198 } 199 200 // 201 // 202 // 203 204 static 205 skc_bool 206 skc_raster_builder_raster_ids_append(struct skc_raster_builder * const raster_builder, 207 skc_raster_t const raster) 208 { 209 SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->raster_ids.ring)); 210 211 raster_builder->raster_ids.extent[skc_extent_ring_wip_index_inc(&raster_builder->raster_ids.ring)] = raster; 212 213 return skc_extent_ring_wip_is_full(&raster_builder->raster_ids.ring); 214 } 215 216 // 217 // 218 // 219 220 static 221 void 222 skc_raster_builder_checkpoint(struct skc_raster_builder * const raster_builder) 223 { 224 skc_extent_ring_checkpoint(&raster_builder->path_ids .ring); 225 skc_extent_ring_checkpoint(&raster_builder->transforms.ring); 226 skc_extent_ring_checkpoint(&raster_builder->clips .ring); 227 skc_extent_ring_checkpoint(&raster_builder->fill_cmds .ring); 228 skc_extent_ring_checkpoint(&raster_builder->raster_ids.ring); 229 } 230 231 // 232 // RASTER OPS 233 // 234 235 skc_err 236 skc_raster_begin(skc_raster_builder_t raster_builder) 237 { 238 SKC_ASSERT_STATE_TRANSITION(SKC_RASTER_BUILDER_STATE_READY, 239 SKC_RASTER_BUILDER_STATE_BUILDING, 240 raster_builder); 241 242 return SKC_ERR_SUCCESS; 243 } 244 245 skc_err 246 skc_raster_end(skc_raster_builder_t raster_builder, skc_raster_t * raster) 247 { 248 SKC_ASSERT_STATE_TRANSITION(SKC_RASTER_BUILDER_STATE_BUILDING, 249 SKC_RASTER_BUILDER_STATE_READY, 250 raster_builder); 251 // get a raster id 252 raster_builder->end(raster_builder->impl,raster); 253 254 // if cohort is full then launch 255 skc_bool const snap = skc_raster_builder_raster_ids_append(raster_builder,*raster); 256 257 // checkpoint the current ring range 258 skc_raster_builder_checkpoint(raster_builder); 259 260 // snapshot and force start because the cohort is full -- no need to wait 261 if (snap) 262 raster_builder->force(raster_builder->impl); 263 264 // add guard bit 265 *raster |= SKC_TYPED_HANDLE_TYPE_IS_RASTER; // FIXME -- the guard bit can be buried 266 267 return SKC_ERR_SUCCESS; 268 } 269 270 // 271 // PATH-TO-RASTER OPS 272 // 273 274 skc_err 275 skc_raster_add_filled(skc_raster_builder_t raster_builder, 276 skc_path_t path, 277 skc_transform_weakref_t * transform_weakref, 278 float const * transform, 279 skc_raster_clip_weakref_t * raster_clip_weakref, 280 float const * raster_clip) 281 { 282 SKC_ASSERT_STATE_ASSERT(SKC_RASTER_BUILDER_STATE_BUILDING,raster_builder); 283 284 // 285 // validate and retain the path handle before proceeding 286 // 287 skc_err err = raster_builder->add(raster_builder->impl,&path,1); 288 289 if (err) 290 return err; 291 292 // mask off the guard bits 293 path = SKC_TYPED_HANDLE_TO_HANDLE(path); 294 295 // 296 // build the command... 297 // 298 union skc_cmd_fill cmd; 299 300 // append path to ring 301 skc_bool snap = skc_raster_builder_path_ids_append(raster_builder,&cmd,path); 302 303 // append transform 304 snap = skc_raster_builder_transforms_append(raster_builder,&cmd,transform_weakref,transform) || snap; 305 306 // append raster clip 307 snap = skc_raster_builder_clips_append(raster_builder,&cmd,raster_clip_weakref,raster_clip) || snap; 308 309 // append fill command 310 snap = skc_raster_builder_cmds_append(raster_builder,&cmd) || snap; 311 312 // snapshot and lazily start 313 if (snap) 314 raster_builder->start(raster_builder->impl); 315 316 return SKC_ERR_SUCCESS; 317 } 318 319 // 320 // 321 // 322