Home | History | Annotate | Download | only in skc
      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