blob: b86ff93d08fb062c338950c1a67f3603b34956b9 [file] [log] [blame]
/*
* 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;
}
//
//
//