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