Index: /trunk/src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py	(revision 56472)
+++ /trunk/src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py	(revision 56473)
@@ -49,4 +49,8 @@
 print 'struct _copy_list_node;'
 print ''
+print '/* Prototype for SPU internal state load/unload callbacks. */'
+print ''
+print 'typedef int (*SPUStateFunc_t)(void *);'
+print ''
 print '/* The SPU dispatch table */'
 print 'typedef struct _spu_dispatch_table {'
@@ -60,4 +64,6 @@
 	int mark;
 	void *server;		
+	SPUStateFunc_t spu_save_state; /* Save SPU internal state callback (optional) */
+	SPUStateFunc_t spu_load_state; /* Load SPU internal state callback (optional) */
 } SPUDispatchTable;
 
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c	(revision 56472)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c	(revision 56473)
@@ -1684,6 +1684,11 @@
 
 #ifdef VBOX_WITH_CR_DISPLAY_LISTS
-    rc = crDLMSaveState();
-    AssertRCReturn(rc, rc);
+    if (cr_server.head_spu->dispatch_table.spu_save_state)
+    {
+        rc = cr_server.head_spu->dispatch_table.spu_save_state("NULL");
+        AssertRCReturn(rc, rc);
+    }
+    else
+        crDebug("Do not save %s SPU state: no interface exported.", cr_server.head_spu->name);
 #endif
 
Index: /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm.c	(revision 56472)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm.c	(revision 56473)
@@ -614,88 +614,4 @@
 }
 
-CRDLMError DLM_APIENTRY crDLMGetDLMBounds(CRDLM *dlm, unsigned long listIdentifier, CRDLMBounds *bounds)
-{
-	DLMListInfo *listInfo
-		= (DLMListInfo *) crHashtableSearch(dlm->displayLists, listIdentifier);
-	if (listInfo) {
-		*bounds = listInfo->bbox;
-		return GL_NO_ERROR;
-	}
-	else {
-		return GL_INVALID_OPERATION;
-	}
-}
-
-CRDLMError DLM_APIENTRY crDLMGetBounds(unsigned long listIdentifier, CRDLMBounds *bounds)
-{
-    CRDLMContextState *listState = CURRENT_STATE();
-    if (listState) {
-	return crDLMGetDLMBounds(listState->dlm, listIdentifier, bounds);
-    }
-    else {
-	return CRDLM_ERROR_STATE;
-    }
-}
-
-
-/**
- * Set the bounding box for a display list.
- */
-void DLM_APIENTRY crDLMSetDLMBounds(CRDLM *dlm, unsigned long listIdentifier,
-               double xmin, double ymin, double zmin,
-               double xmax, double ymax, double zmax)
-{
-	DLMListInfo *listInfo
-		= (DLMListInfo *) crHashtableSearch(dlm->displayLists, listIdentifier);
-	if (!listInfo) {
-		/* allocate a list info now */
-		CRDLMContextState *listState = CURRENT_STATE();
-		listInfo = (DLMListInfo *) crCalloc(sizeof(DLMListInfo));
-		crHashtableReplace(listState->dlm->displayLists,
-											 listIdentifier, listInfo, crdlm_free_list);
-	}
-	if (listInfo) {
-		listInfo->bbox.xmin = xmin;
-		listInfo->bbox.ymin = ymin;
-		listInfo->bbox.zmin = zmin;
-		listInfo->bbox.xmax = xmax;
-		listInfo->bbox.ymax = ymax;
-		listInfo->bbox.zmax = zmax;
-	}
-}
-
-void DLM_APIENTRY crDLMSetBounds(unsigned long listIdentifier,
-               double xmin, double ymin, double zmin,
-               double xmax, double ymax, double zmax)
-{
-    CRDLMContextState *listState = CURRENT_STATE();
-    if (listState) {
-	crDLMSetDLMBounds(listState->dlm, listIdentifier,
-	    xmin, ymin, zmin, xmax, ymax, zmax);
-    }
-}
-
-/**
- * Return GL_TRUE if the given list has a valid bounding box
- */
-GLboolean DLM_APIENTRY crDLMListHasDLMBounds(CRDLM *dlm, unsigned long listIdentifier)
-{
-	DLMListInfo *listInfo
-		= (DLMListInfo *) crHashtableSearch(dlm->displayLists, listIdentifier);
-	if (listInfo)
-		return listInfo->bbox.xmin != FLT_MAX;
-	else
-		return GL_FALSE;
-}
-
-GLboolean DLM_APIENTRY crDLMListHasBounds(unsigned long listIdentifier)
-{
-    CRDLMContextState *listState = CURRENT_STATE();
-    if (listState) {
-	return crDLMListHasDLMBounds(listState->dlm, listIdentifier);
-    }
-    return 0;
-}
-
 /*
  * Return id of list currently being compiled.  Returns 0 of there's no
@@ -734,6 +650,32 @@
 }
 
+static void crDLMSaveListsCb(unsigned long key, void *pData1, void *pData2 /* unused */ )
+{
+    DLMListInfo *pListInfo = (DLMListInfo*)pData1;
+
+    if (pListInfo)
+    {
+        crDebug("Saving Display Lists: found ID=%u, numInstances=%d, references=%p.",
+            key, pListInfo->numInstances, pListInfo->references);
+
+        DLMInstanceList *pInstance = pListInfo->first;
+        while (pInstance) {
+            crDebug("\t%p", pInstance->execute);
+            pInstance = pInstance->next;
+        }
+    }
+    else
+        crError("Saving Display Lists: found record with no data. Skipping.");
+}
+
 int32_t DLM_APIENTRY crDLMSaveState(void)
 {
+    CRDLMContextState *pListState = CURRENT_STATE();
+
+    if (pListState)
+        crHashtableWalk(pListState->dlm->displayLists, crDLMSaveListsCb, (void *)NULL);
+    else
+        crDebug("Saving Display Lists: no data to save.");
+
     return 0;
 }
Index: /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py	(revision 56472)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py	(revision 56473)
@@ -86,4 +86,5 @@
 	print '	DLMInstanceList *stateNext;'
 	print '	int cbInstance;'
+	print '	VBoxDLOpCode iVBoxOpCode;'
 	print '	void (DLM_APIENTRY *execute)(DLMInstanceList *instance, SPUDispatchTable *dispatchTable);'
 	for (name, type, vecSize) in params:
@@ -323,4 +324,7 @@
 	print '\tinstance->cbInstance = sizeof(struct instance%s);' % functionName
 	
+	# Set OPCODE.
+	print '\tinstance->iVBoxOpCode = VBOX_DL_OPCODE_%s;' % functionName
+	
 	# If there's a pointer parameter, apply it.
 	if len(pointers) == 1:
Index: /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_header.py
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_header.py	(revision 56472)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_header.py	(revision 56473)
@@ -7,4 +7,6 @@
 # mode is "header" or "defs"
 mode = sys.argv[1]
+
+keys = apiutil.GetDispatchedFunctions(sys.argv[2]+"/APIspec.txt")
 
 # Any new function implemented in the DLM has to have an entry added here.
@@ -36,11 +38,5 @@
 	('CRDLMError DLM_APIENTRY', 'crDLMDeleteListContent', 'CRDLM *dlm, unsigned long listIdentifier'),
 	('int DLM_APIENTRY', 'crDLMGetReferences', 'CRDLM *dlm, unsigned long listIdentifier, int firstIndex, int sizeofBuffer, unsigned int *buffer'),
-	('CRDLMError DLM_APIENTRY', 'crDLMGetDLMBounds', 'CRDLM *dlm, unsigned long listIdentifier, CRDLMBounds *bounds'),
-	('CRDLMError DLM_APIENTRY', 'crDLMGetBounds', 'unsigned long listIdentifier, CRDLMBounds *bounds'),
-	('void DLM_APIENTRY', 'crDLMSetDLMBounds', 'CRDLM *dlm, unsigned long listIdentifier, double xmin, double ymin, double zmin, double xmax, double ymax, double zmax'),
-	('void DLM_APIENTRY', 'crDLMSetBounds', 'unsigned long listIdentifier, double xmin, double ymin, double zmin, double xmax, double ymax, double zmax'),
 	('void DLM_APIENTRY', 'crDLMComputeBoundingBox', 'unsigned long listId'),
-	('GLboolean DLM_APIENTRY', 'crDLMListHasDLMBounds', 'CRDLM *dlm, unsigned long listIdentifier'),
-	('GLboolean DLM_APIENTRY', 'crDLMListHasBounds', 'unsigned long listIdentifier'),
 	('GLuint DLM_APIENTRY', 'crDLMGetCurrentList', 'void'),
 	('GLenum DLM_APIENTRY', 'crDLMGetCurrentMode', 'void'),
@@ -59,5 +55,5 @@
 
 if mode == 'header':
-	print """#ifndef CR_DLM_H
+    print """#ifndef CR_DLM_H
 
 /* DO NOT EDIT.  This file is auto-generated by %s. */
@@ -79,5 +75,16 @@
 #include "cr_threads.h"
 #endif
-
+""" % os.path.basename(sys.argv[0])
+
+    # Generate operation codes enum to be used for saving and restoring lists.
+    print "/* OpCodes codes enum to be used for saving and restoring lists. */"
+    print "typedef enum {"
+
+    for func_name in keys:
+        print "    VBOX_DL_OPCODE_%s," % func_name
+
+    print "} VBoxDLOpCode;"
+
+    print """
 /* 3D bounding box */
 typedef struct {
@@ -96,5 +103,6 @@
 	struct DLMInstanceList *next;
 	struct DLMInstanceList *stateNext;
-	int    cbInstance;
+	int                     cbInstance;
+	VBoxDLOpCode            iVBoxOpCode; /* This field name should not interfere w/ OpenGL function parameters names (for example w/ param 'opcode' for glLogicOp()). */
 	void (*execute)(struct DLMInstanceList *instance, SPUDispatchTable *dispatchTable);
 } DLMInstanceList;
@@ -191,5 +199,5 @@
 extern "C" {
 #endif
-""" % os.path.basename(sys.argv[0])
+"""
 elif mode == 'defs':
 	apiutil.CopyrightDef()
@@ -215,5 +223,5 @@
 
 
-keys = apiutil.GetDispatchedFunctions(sys.argv[2]+"/APIspec.txt")
+
 for func_name in keys:
 	props = apiutil.Properties(func_name)
Index: /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_lists.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_lists.c	(revision 56472)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/dlm/dlm_lists.c	(revision 56473)
@@ -95,4 +95,6 @@
     listState->currentListIdentifier = listIdentifier;
     listState->currentListMode = mode;
+
+    crDebug("Display Lists: create new with guest ID %u.", listIdentifier);
 }
 
Index: /trunk/src/VBox/HostServices/SharedOpenGL/expando/expandospu_init.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/expando/expandospu_init.c	(revision 56472)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/expando/expandospu_init.c	(revision 56473)
@@ -19,4 +19,12 @@
 	_cr_expando_table /* THE ACTUAL FUNCTIONS */
 };
+
+static int
+expandoSPUSaveState(void *pData)
+{
+    crDebug("Saving state of Expando SPU.");
+    crDLMSaveState();
+    return 0;
+}
 
 static SPUFunctions *
@@ -48,4 +56,7 @@
 	/* We'll be using the state tracker for each context */
 	crStateInit();
+
+    /* Export optional interfaces for SPU save/restore. */
+    self->dispatch_table.spu_save_state = expandoSPUSaveState;
 
 	return &expando_functions;
