commit 6a611f84688294e853355714e5a29972877cffc3
parent aa50add43ae7972d00b1024f171869e783481c5b
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 10 Sep 2015 09:23:20 +0200
Fix issues in the s3d_scene instancing
No error occurs if a scene is instantiated several times in another
scene. A scene cannot own an instance of itself.
Diffstat:
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -408,7 +408,17 @@ scene_sync(struct s3d_scene* scn, const int session_mask)
res_T res = RES_OK;
ASSERT(scn);
- if(scn->session_mask != 0) {
+ if((session_mask & S3D_INSTANCE) != 0
+ && (scn->session_mask & S3D_INSTANCE) != 0) {
+ /* The scene was already synced as an instance. Discard sync process */
+ return RES_OK;
+ } else if(scn->session_mask != 0) {
+ /* The scene cannot be synced several times exepted if it is instantiated */
+ res = RES_BAD_OP;
+ goto error;
+ }
+
+ if((session_mask & S3D_INSTANCE) == 0 && scn->session_mask != 0) {
res = RES_BAD_OP;
goto error;
}
@@ -417,6 +427,11 @@ scene_sync(struct s3d_scene* scn, const int session_mask)
shape = CONTAINER_OF(node, struct s3d_shape, scene_attachment);
switch(shape->type) {
case GEOM_INSTANCE:
+ /* One instancing level is supported */
+ if((session_mask & S3D_INSTANCE) != 0) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
res = scene_register_instance(scn, shape, session_mask);
break;
case GEOM_MESH:
@@ -567,6 +582,8 @@ s3d_scene_attach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
return RES_BAD_ARG;
if(!is_list_empty(&shape->scene_attachment))
return RES_BAD_ARG;
+ if(shape->type == GEOM_INSTANCE && shape->data.instance->scene == scn)
+ return RES_BAD_ARG;
list_add_tail(&scn->shapes, &shape->scene_attachment);
S3D(shape_ref_get(shape));
diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c
@@ -39,6 +39,8 @@ main(int argc, char** argv)
struct mem_allocator allocator;
struct s3d_device* dev;
struct s3d_scene* scn;
+ struct s3d_scene* scn2;
+ struct s3d_scene* scn3;
struct s3d_shape* shapes[4];
const size_t nshapes = sizeof(shapes)/sizeof(struct s3d_shape*);
size_t i;
@@ -56,6 +58,8 @@ main(int argc, char** argv)
CHECK(s3d_scene_create(dev, NULL), RES_BAD_ARG);
CHECK(s3d_scene_create(NULL, &scn), RES_BAD_ARG);
CHECK(s3d_scene_create(dev, &scn), RES_OK);
+ CHECK(s3d_scene_create(dev, &scn2), RES_OK);
+ CHECK(s3d_scene_create(dev, &scn3), RES_OK);
CHECK(s3d_scene_attach_shape(NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_attach_shape(scn, NULL), RES_BAD_ARG);
@@ -89,6 +93,7 @@ main(int argc, char** argv)
CHECK(s3d_scene_clear(scn), RES_OK);
CHECK(s3d_scene_clear(scn), RES_OK);
CHECK(s3d_scene_instantiate(scn, shapes + 2), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn, shapes[2]), RES_BAD_ARG);
CHECK(s3d_scene_get_session_mask(NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_get_session_mask(scn, NULL), RES_BAD_ARG);
@@ -116,17 +121,29 @@ main(int argc, char** argv)
CHECK(s3d_scene_get_session_mask(scn, &mask), RES_OK);
CHECK(mask, 0);
+ CHECK(s3d_scene_attach_shape(scn2, shapes[1]), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn2, shapes[2]), RES_OK);
+ CHECK(s3d_scene_begin_session(scn2, S3D_SAMPLE|S3D_TRACE), RES_OK);
+ CHECK(s3d_scene_end_session(scn2), RES_OK);
+
+ CHECK(s3d_scene_instantiate(scn2, shapes + 3), RES_OK);
+ CHECK(s3d_scene_attach_shape(scn3, shapes[3]), RES_OK);
+ CHECK(s3d_scene_begin_session(scn3, S3D_SAMPLE|S3D_TRACE), RES_BAD_ARG);
+
CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_OK);
CHECK(s3d_shape_ref_put(shapes[0]), RES_OK);
CHECK(s3d_shape_ref_put(shapes[1]), RES_OK);
CHECK(s3d_shape_ref_put(shapes[2]), RES_OK);
+ CHECK(s3d_shape_ref_put(shapes[3]), RES_OK);
CHECK(s3d_scene_ref_get(NULL), RES_BAD_ARG);
CHECK(s3d_scene_ref_get(scn), RES_OK);
CHECK(s3d_scene_ref_put(NULL), RES_BAD_ARG);
CHECK(s3d_scene_ref_put(scn), RES_OK);
CHECK(s3d_scene_ref_put(scn), RES_OK);
+ CHECK(s3d_scene_ref_put(scn2), RES_OK);
+ CHECK(s3d_scene_ref_put(scn3), RES_OK);
CHECK(s3d_device_ref_put(dev), RES_OK);;