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
skc_raster_builder_retain(skc_raster_builder_t raster_builder)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
skc_raster_builder_release(skc_raster_builder_t raster_builder)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
skc_raster_builder_path_ids_append(struct skc_raster_builder * const raster_builder,union skc_cmd_fill * const cmd,skc_path_t const path)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
skc_raster_builder_transforms_append(struct skc_raster_builder * const raster_builder,union skc_cmd_fill * const cmd,skc_transform_weakref_t * const transform_weakref,skc_float const * const transform)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
skc_raster_builder_clips_append(struct skc_raster_builder * const raster_builder,union skc_cmd_fill * const cmd,skc_raster_clip_weakref_t * const raster_clip_weakref,skc_float const * const raster_clip)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
skc_raster_builder_cmds_append(struct skc_raster_builder * const raster_builder,union skc_cmd_fill * const cmd)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
skc_raster_builder_raster_ids_append(struct skc_raster_builder * const raster_builder,skc_raster_t const raster)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
skc_raster_builder_checkpoint(struct skc_raster_builder * const raster_builder)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
skc_raster_begin(skc_raster_builder_t raster_builder)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
skc_raster_end(skc_raster_builder_t raster_builder,skc_raster_t * raster)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
skc_raster_add_filled(skc_raster_builder_t raster_builder,skc_path_t path,skc_transform_weakref_t * transform_weakref,float const * transform,skc_raster_clip_weakref_t * raster_clip_weakref,float const * raster_clip)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