brender-1997/softrend/sstate.c
2022-05-03 14:31:40 -07:00

301 lines
8.2 KiB
C

/*
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: sstate.c 2.12 1997/02/17 12:28:59 jon Exp $
* $Locker: $
*
* Stored renderer state
*/
#include <stddef.h>
#include <string.h>
#include "drv.h"
#include "shortcut.h"
#include "brassert.h"
BR_RCS_ID("$Id: sstate.c 2.12 1997/02/17 12:28:59 jon Exp $");
/*
* Default dispatch table for renderer type (defined at and of file)
*/
static const struct br_renderer_state_stored_dispatch rendererStateStoredDispatch;
/*
* Geometry format info. template
*/
#define F(f) offsetof(struct br_renderer_state_stored, f)
static struct br_tv_template_entry rendererStateStoredTemplateEntries[] = {
{BRT_IDENTIFIER_CSTR, 0, F(identifier), BRTV_QUERY | BRTV_ALL, BRTV_CONV_COPY, },
{BRT_RENDERER_O, 0, F(renderer), BRTV_QUERY | BRTV_ALL, BRTV_CONV_COPY, },
{BRT_PARTS_U32, 0, F(valid), BRTV_QUERY | BRTV_ALL, BRTV_CONV_COPY, },
{DEV(PRIMITIVE_STATE_O), F(pstate), BRTV_QUERY | BRTV_ALL, BRTV_CONV_COPY, },
};
#undef F
/*
* Utility functions to copy all or part of a state from one place to another
* where either source or destination is a stored state
*
* The destination recalc. bitmasks are updated appropiately
*/
br_error StateCopyToStored(struct br_renderer_state_stored *dest, struct state_all *src, br_uint_32 copy_mask, void *res)
{
if (copy_mask & MASK_CACHED_STATES)
copy_mask |= MASK_STATE_CACHE;
/*
* Restrict copy_mask to parts held in stored states (should it return
* an error if valid parts will be lost?)
*/
copy_mask &= MASK_STATE_STORED;
/*
* Restrict copy_mask to valid source parts
*/
copy_mask &= src->valid;
/*
* Merge valid mask into destination
*/
dest->valid |= copy_mask;
/*
* See if any parts of primitive state need copying
*/
if(copy_mask & ~MASK_STATE_LOCAL) {
#if COPY_PRIMITIVE_STATES
/*
* Kinda gross hack for <REDACTEDGAME>. We don't actually copy primitive state, we just copy
* pointers where possible, so only save the state if the pointers are different.
*/
if (dest->pstate != src->pstate)
#endif
if(dest->pstate) {
if(src->pstate)
PrimitiveStateStateCopy(dest->pstate, src->pstate, copy_mask);
else
PrimitiveStateStateDefault(dest->pstate, copy_mask);
} else if(src->pstate) {
/*
* Create new dest. state and copy into it
*/
if(PrimitiveLibraryStateNew(src->renderer->plib, &dest->pstate) == BRE_OK) {
/*
* Attach new primitive state to given resource parent
*/
if(res)
BrResAdd(res,dest->pstate);
PrimitiveStateStateCopy(dest->pstate, src->pstate, copy_mask);
}
}
}
if(copy_mask & MASK_STATE_CULL && dest->cull.timestamp != src->cull.timestamp)
dest->cull = src->cull;
if(copy_mask & MASK_STATE_SURFACE && dest->surface.timestamp != src->surface.timestamp)
dest->surface = src->surface;
/*
* Copy cache, or mark destination's cache as invalid as necessary
*/
if (copy_mask & MASK_STATE_CACHE)
if (src->cache.valid && dest->cull.timestamp == src->cull.timestamp &&
dest->surface.timestamp == src->surface.timestamp) {
if (dest->timestamp_cache != src->timestamp_cache) {
dest->cache = src->cache;
dest->timestamp_cache = src->timestamp_cache;
}
} else
dest->cache.valid = BR_FALSE;
return BRE_OK;
}
br_error StateCopyFromStored(struct state_all *dest, struct br_renderer_state_stored *src, br_uint_32 copy_mask, void *res)
{
if (copy_mask & MASK_CACHED_STATES)
copy_mask |= MASK_STATE_CACHE;
/*
* Restrict copy_mask to parts held in stored states (should it return
* an error if requested parts will not be copied?)
*/
copy_mask &= MASK_STATE_STORED;
/*
* Restrict copy_mask to valid source parts
*/
copy_mask &= src->valid;
/*
* Merge valid mask into destination
*/
dest->valid |= copy_mask;
#if COPY_PRIMITIVE_STATES
/*
* Kinda gross hack for <REDACTEDGAME>. We don't actually copy primitive state, we just copy
* pointers where possible, but we may have to part of the state back
*/
if (src->pstate != NULL) {
if (dest->pstate != NULL)
PrimitiveStateStateCopy(src->pstate, dest->pstate, ~copy_mask);
else
PrimitiveStateStateDefault(src->pstate, ~copy_mask);
dest->pstate = src->pstate;
}
#else
/*
* See if any parts of primitive state need copying
*/
if(copy_mask & ~MASK_STATE_LOCAL) {
if(dest->pstate) {
if(src->pstate)
PrimitiveStateStateCopy(dest->pstate, src->pstate, copy_mask);
else
PrimitiveStateStateDefault(dest->pstate, copy_mask);
} else if(src->pstate) {
/*
* Create new dest. state and copy into it
*/
if(PrimitiveLibraryStateNew(src->renderer->plib, &dest->pstate) == BRE_OK) {
/*
* Attach new primitive state to given resource parent
*/
if(res)
BrResAdd(res,dest->pstate);
PrimitiveStateStateCopy(dest->pstate, src->pstate, copy_mask);
}
}
}
#endif
if(copy_mask & MASK_STATE_CULL && dest->cull.timestamp != src->cull.timestamp)
dest->cull = src->cull;
if(copy_mask & MASK_STATE_SURFACE && dest->surface.timestamp != src->surface.timestamp)
dest->surface = src->surface;
/*
* Copy cache, or mark destination's cache as invalid as necessary
*/
if (copy_mask & MASK_STATE_CACHE)
if (src->cache.valid && dest->cull.timestamp == src->cull.timestamp &&
dest->surface.timestamp == src->surface.timestamp) {
if (dest->timestamp_cache != src->timestamp_cache) {
dest->cache = src->cache;
dest->timestamp_cache = src->timestamp_cache;
}
} else
dest->cache.valid = BR_FALSE;
return BRE_OK;
}
/*
* Allocate a stored state
*/
br_renderer_state_stored * RendererStateStoredSoftAllocate(br_renderer *renderer,
struct state_all *base_state, br_uint_32 m, br_token_value *tv)
{
br_renderer_state_stored * self;
self = BrResAllocate(renderer->device, sizeof(*self), BR_MEMORY_OBJECT_DATA);
if(self == NULL)
return NULL;
self->dispatch = (struct br_renderer_state_stored_dispatch *)&rendererStateStoredDispatch;
self->identifier = "Renderer-State-Stored";
self->device = renderer->device;
self->renderer = renderer;
/*
* Copy initial state
*/
StateCopyToStored(self, base_state, m, self);
ObjectContainerAddFront(renderer, (br_object *)self);
return self;
}
static void BR_CMETHOD_DECL(br_renderer_state_stored_soft, free)(br_renderer_state_stored *self)
{
ObjectContainerRemove(self->renderer, (br_object *)self);
/*
* Any associated primitive state will have been attached as a resource
*/
BrResFreeNoCallback(self);
}
static br_token BR_CMETHOD_DECL(br_renderer_state_stored_soft, type)(br_renderer_state_stored *self)
{
return BRT_RENDERER_STATE_STORED;
}
static br_boolean BR_CMETHOD_DECL(br_renderer_state_stored_soft, isType)(br_renderer_state_stored *self, br_token t)
{
return (t == BRT_RENDERER_STATE_STORED) || (t == BRT_OBJECT);
}
static br_int_32 BR_CMETHOD_DECL(br_renderer_state_stored_soft, space)(br_renderer_state_stored *self)
{
return sizeof(br_renderer_state_stored);
}
static struct br_tv_template * BR_CMETHOD_DECL(br_renderer_state_stored_soft, templateQuery)
(br_renderer_state_stored *self)
{
if(self->device->templates.rendererStateStoredTemplate == NULL)
self->device->templates.rendererStateStoredTemplate = BrTVTemplateAllocate(self->device,
(br_tv_template_entry *)rendererStateStoredTemplateEntries,
BR_ASIZE(rendererStateStoredTemplateEntries));
return self->device->templates.rendererStateStoredTemplate;
}
/*
* Default dispatch table for renderer type (defined at and of file)
*/
static const struct br_renderer_state_stored_dispatch rendererStateStoredDispatch = {
NULL,
NULL,
NULL,
NULL,
BR_CMETHOD_REF(br_renderer_state_stored_soft, free),
BR_CMETHOD_REF(br_object_soft, identifier),
BR_CMETHOD_REF(br_renderer_state_stored_soft, type),
BR_CMETHOD_REF(br_renderer_state_stored_soft, isType),
BR_CMETHOD_REF(br_object_soft, device),
BR_CMETHOD_REF(br_renderer_state_stored_soft, space),
BR_CMETHOD_REF(br_renderer_state_stored_soft, templateQuery),
BR_CMETHOD_REF(br_object, query),
BR_CMETHOD_REF(br_object, queryBuffer),
BR_CMETHOD_REF(br_object, queryMany),
BR_CMETHOD_REF(br_object, queryManySize),
BR_CMETHOD_REF(br_object, queryAll),
BR_CMETHOD_REF(br_object, queryAllSize),
};