| /* |
| * Copyright 2017 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can |
| * be found in the LICENSE file. |
| * |
| */ |
| |
| // |
| // |
| // |
| |
| #include <stdlib.h> |
| #include <memory.h> |
| #include <float.h> |
| |
| #include "raster_builder.h" |
| |
| #include "context.h" |
| #include "weakref.h" |
| |
| #include "scheduler.h" |
| #include "handle.h" |
| |
| #include "common.h" |
| |
| // |
| // |
| // |
| |
| #ifndef NDEBUG |
| |
| #include <stdio.h> |
| |
| #define SKC_CONTEXT_WAIT_DEBUG(p) \ |
| fprintf(stderr,"WAITING ON: " p "\n") |
| |
| #else |
| |
| #define SKC_CONTEXT_WAIT_DEBUG(p) |
| |
| #endif |
| |
| // |
| // |
| // |
| |
| #define SKC_CONTEXT_WAIT_WHILE(c,p) \ |
| while (p) { \ |
| SKC_CONTEXT_WAIT_DEBUG(#p); \ |
| skc_context_wait(c); \ |
| } |
| |
| // |
| // |
| // |
| |
| #if 0 |
| |
| // |
| // IDENTITY TRANSFORM |
| // |
| |
| static |
| float const skc_transform_identity[8] = |
| { |
| 1.0f, 0.0f, 0.0f, // sx shx tx |
| 0.0f, 1.0f, 0.0f, // shy sy ty |
| 0.0f, 0.0f // w0 w1 1 <-- always 1 |
| }; |
| |
| // float const * const skc_transform_identity_ptr = skc_transform_identity; |
| |
| // |
| // DEFAULT RASTER CLIP |
| // |
| |
| static |
| float const skc_raster_clip_default[4] = |
| { |
| -FLT_MAX, -FLT_MAX, // lower left corner of bounding box |
| +FLT_MAX, +FLT_MAX // upper right corner of bounding box |
| }; |
| |
| // float const * const skc_raster_clip_default_ptr = skc_raster_clip_default; |
| |
| #endif |
| |
| // |
| // |
| // |
| |
| skc_err |
| skc_raster_builder_retain(skc_raster_builder_t raster_builder) |
| { |
| raster_builder->refcount += 1; |
| |
| return SKC_ERR_SUCCESS; |
| } |
| |
| //xbli |
| // |
| // |
| |
| skc_err |
| skc_raster_builder_release(skc_raster_builder_t raster_builder) |
| { |
| SKC_ASSERT_STATE_ASSERT(SKC_RASTER_BUILDER_STATE_READY,raster_builder); |
| |
| raster_builder->release(raster_builder->impl); |
| |
| return SKC_ERR_SUCCESS; |
| } |
| |
| // |
| // |
| // |
| |
| static |
| 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) |
| { |
| SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->path_ids.ring)); |
| |
| cmd->path = path; |
| |
| raster_builder->path_ids.extent[skc_extent_ring_wip_index_inc(&raster_builder->path_ids.ring)] = path; |
| |
| return skc_extent_ring_wip_is_full(&raster_builder->path_ids.ring); |
| } |
| |
| static |
| 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) |
| { |
| // |
| // FIXME -- check weakref |
| // |
| SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->transforms.ring)); |
| |
| cmd->transform = skc_extent_ring_wip_count(&raster_builder->transforms.ring); |
| |
| skc_uint const base = skc_extent_ring_wip_index_inc(&raster_builder->transforms.ring); |
| |
| memcpy(raster_builder->transforms.extent[base].f32a8,transform,sizeof(skc_float8)); |
| |
| return skc_extent_ring_wip_is_full(&raster_builder->transforms.ring); |
| } |
| |
| static |
| 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) |
| { |
| // |
| // FIXME -- check weakref |
| // |
| SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->clips.ring)); |
| |
| cmd->clip = skc_extent_ring_wip_count(&raster_builder->clips.ring); |
| |
| skc_uint const base = skc_extent_ring_wip_index_inc(&raster_builder->clips.ring); |
| |
| memcpy(raster_builder->clips.extent[base].f32a4,raster_clip,sizeof(skc_float4)); |
| |
| return skc_extent_ring_wip_is_full(&raster_builder->clips.ring); |
| } |
| |
| static |
| skc_bool |
| skc_raster_builder_cmds_append(struct skc_raster_builder * const raster_builder, |
| union skc_cmd_fill * const cmd) |
| { |
| SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->fill_cmds.ring)); |
| |
| cmd->cohort = skc_extent_ring_wip_count(&raster_builder->raster_ids.ring); |
| |
| skc_uint const base = skc_extent_ring_wip_index_inc(&raster_builder->fill_cmds.ring); |
| |
| raster_builder->fill_cmds.extent[base] = *cmd; |
| |
| #if 0 |
| fprintf(stderr,"[ %4u, %4u, %4u, %4u ]\n", |
| cmd->path, |
| cmd->transform, |
| cmd->clip, |
| cmd->cohort); |
| #endif |
| |
| return skc_extent_ring_wip_is_full(&raster_builder->fill_cmds.ring); |
| } |
| |
| // |
| // |
| // |
| |
| static |
| skc_bool |
| skc_raster_builder_raster_ids_append(struct skc_raster_builder * const raster_builder, |
| skc_raster_t const raster) |
| { |
| SKC_CONTEXT_WAIT_WHILE(raster_builder->context,skc_extent_ring_is_full(&raster_builder->raster_ids.ring)); |
| |
| raster_builder->raster_ids.extent[skc_extent_ring_wip_index_inc(&raster_builder->raster_ids.ring)] = raster; |
| |
| return skc_extent_ring_wip_is_full(&raster_builder->raster_ids.ring); |
| } |
| |
| // |
| // |
| // |
| |
| static |
| void |
| skc_raster_builder_checkpoint(struct skc_raster_builder * const raster_builder) |
| { |
| skc_extent_ring_checkpoint(&raster_builder->path_ids .ring); |
| skc_extent_ring_checkpoint(&raster_builder->transforms.ring); |
| skc_extent_ring_checkpoint(&raster_builder->clips .ring); |
| skc_extent_ring_checkpoint(&raster_builder->fill_cmds .ring); |
| skc_extent_ring_checkpoint(&raster_builder->raster_ids.ring); |
| } |
| |
| // |
| // RASTER OPS |
| // |
| |
| skc_err |
| skc_raster_begin(skc_raster_builder_t raster_builder) |
| { |
| SKC_ASSERT_STATE_TRANSITION(SKC_RASTER_BUILDER_STATE_READY, |
| SKC_RASTER_BUILDER_STATE_BUILDING, |
| raster_builder); |
| |
| return SKC_ERR_SUCCESS; |
| } |
| |
| skc_err |
| skc_raster_end(skc_raster_builder_t raster_builder, skc_raster_t * raster) |
| { |
| SKC_ASSERT_STATE_TRANSITION(SKC_RASTER_BUILDER_STATE_BUILDING, |
| SKC_RASTER_BUILDER_STATE_READY, |
| raster_builder); |
| // get a raster id |
| raster_builder->end(raster_builder->impl,raster); |
| |
| // if cohort is full then launch |
| skc_bool const snap = skc_raster_builder_raster_ids_append(raster_builder,*raster); |
| |
| // checkpoint the current ring range |
| skc_raster_builder_checkpoint(raster_builder); |
| |
| // snapshot and force start because the cohort is full -- no need to wait |
| if (snap) |
| raster_builder->force(raster_builder->impl); |
| |
| // add guard bit |
| *raster |= SKC_TYPED_HANDLE_TYPE_IS_RASTER; // FIXME -- the guard bit can be buried |
| |
| return SKC_ERR_SUCCESS; |
| } |
| |
| // |
| // PATH-TO-RASTER OPS |
| // |
| |
| 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) |
| { |
| SKC_ASSERT_STATE_ASSERT(SKC_RASTER_BUILDER_STATE_BUILDING,raster_builder); |
| |
| // |
| // validate and retain the path handle before proceeding |
| // |
| skc_err err = raster_builder->add(raster_builder->impl,&path,1); |
| |
| if (err) |
| return err; |
| |
| // mask off the guard bits |
| path = SKC_TYPED_HANDLE_TO_HANDLE(path); |
| |
| // |
| // build the command... |
| // |
| union skc_cmd_fill cmd; |
| |
| // append path to ring |
| skc_bool snap = skc_raster_builder_path_ids_append(raster_builder,&cmd,path); |
| |
| // append transform |
| snap = skc_raster_builder_transforms_append(raster_builder,&cmd,transform_weakref,transform) || snap; |
| |
| // append raster clip |
| snap = skc_raster_builder_clips_append(raster_builder,&cmd,raster_clip_weakref,raster_clip) || snap; |
| |
| // append fill command |
| snap = skc_raster_builder_cmds_append(raster_builder,&cmd) || snap; |
| |
| // snapshot and lazily start |
| if (snap) |
| raster_builder->start(raster_builder->impl); |
| |
| return SKC_ERR_SUCCESS; |
| } |
| |
| // |
| // |
| // |