diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/HostServices/SharedOpenGL/dlm | |
parent | Initial commit. (diff) | |
download | virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/HostServices/SharedOpenGL/dlm')
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/Makefile.kup | 0 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm.c | 575 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm.h | 31 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_arrays.c | 387 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_checklist.c | 51 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_error.c | 56 | ||||
-rwxr-xr-x | src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py | 355 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_header.py | 274 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_lists.c | 452 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_pointers.c | 1125 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_pointers.h | 81 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_special | 21 | ||||
-rw-r--r-- | src/VBox/HostServices/SharedOpenGL/dlm/dlm_state.c | 280 |
13 files changed, 3688 insertions, 0 deletions
diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/Makefile.kup b/src/VBox/HostServices/SharedOpenGL/dlm/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/Makefile.kup diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm.c b/src/VBox/HostServices/SharedOpenGL/dlm/dlm.c new file mode 100644 index 00000000..8ea6c69c --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm.c @@ -0,0 +1,575 @@ +/* $Id: dlm.c $ */ + +#include <float.h> +#include "cr_dlm.h" +#include "cr_mem.h" +#include "dlm.h" + +/** + * \mainpage Dlm + * + * \section DlmIntroduction Introduction + * + * Chromium consists of all the top-level files in the cr + * directory. The dlm module basically takes care of API dispatch, + * and OpenGL state management. + * + */ + +/** + * Module globals: the current DLM state, bound either to each thread, or + * to a global. + */ +#ifdef CHROMIUM_THREADSAFE +CRtsd CRDLMTSDKey; +#else +CRDLMContextState *CRDLMCurrentState = NULL; +#endif + +#define MIN(a,b) ((a)<(b)?(a):(b)) + + +/*************************************************************************/ + +#ifdef CHROMIUM_THREADSAFE +/** + * This is the thread-specific destructor function for the + * data used in the DLM. It's very simple: if a thread exits + * that has DLM-specific data, the data represents the listState + * for the thread. All data and buffers associated with the list + * can be deleted, and the structure itself can be freed. + * + * Most Chromium threads don't have such things; but then, + * if a thread dies elsewhere in Chromium, huge buffers + * of information won't still be floating around in + * unrecoverable allocated areas, either. + */ +static void threadDestructor(void *tsd) +{ + CRDLMContextState *listState = (CRDLMContextState *)tsd; + + if (listState) + { + //if (listState->currentListInfo) + // crdlm_free_list(listState->currentListInfo); + + crFree(listState); + } +} +#endif + +/** + * This function creates and initializes a new display list + * manager. It returns a pointer to the manager, or NULL in + * the case of insufficient memory. The dispatch table pointer + * is passed in to allow the utilities to muck with the table + * to gain functional control when GL calls are made. + */ +CRDLM DLM_APIENTRY *crDLMNewDLM(unsigned int userConfigSize, const CRDLMConfig *userConfig) +{ + CRDLM *dlm; + + /* This is the default configuration. We'll overwrite it later + * with user-supplied configuration information. + */ + CRDLMConfig config = { + CRDLM_DEFAULT_BUFFERSIZE, + }; + + dlm = crAlloc(sizeof(*dlm)); + if (!dlm) { + return NULL; + } + + /* Start off by initializing all entries that require further + * memory allocation, so we can free up all the memory if there's + * a problem. + */ + if (!(dlm->displayLists = crAllocHashtable())) { + crFree(dlm); + return NULL; + } + + /* The creator counts as the first user. */ + dlm->userCount = 1; + +#ifdef CHROMIUM_THREADSAFE + /* This mutex ensures that only one thread is changing the displayLists + * hash at a time. Note that we may also need a mutex to guarantee that + * the hash is not changed by one thread while another thread is + * traversing it; this issue has not yet been resolved. + */ + crInitMutex(&(dlm->dlMutex)); + + /* Although the thread-specific data (TSD) functions will initialize + * the thread key themselves when needed, those functions do not allow + * us to specify a thread destructor. Since a thread could potentially + * exit with considerable memory allocated (e.g. if a thread exits + * after it has issued NewList but before EndList, and while there + * are considerable content buffers allocated), I do the initialization + * myself, in order to be able to reclaim those resources if a thread + * exits. + */ + crInitTSDF(&(dlm->tsdKey), threadDestructor); + crInitTSD(&CRDLMTSDKey); +#endif + + /* Copy over any appropriate configuration values */ + if (userConfig != NULL) { + /* Copy over as much configuration information as is provided. + * Note that if the CRDLMConfig structure strictly grows, this + * allows forward compatability - routines compiled with + * older versions of the structure will only initialize that + * section of the structure that they know about. + */ + crMemcpy((void *)&config, (void *) userConfig, + MIN(userConfigSize, sizeof(config))); + } + dlm->bufferSize = config.bufferSize; + + /* Return the pointer to the newly-allocated display list manager */ + return dlm; +} + +void DLM_APIENTRY crDLMUseDLM(CRDLM *dlm) +{ + DLM_LOCK(dlm); + dlm->userCount++; + DLM_UNLOCK(dlm); +} + +/** + * This routine is called when a context or thread is done with a DLM. + * It maintains an internal count of users, and will only actually destroy + * itself when no one is still using the DLM. + */ +void DLM_APIENTRY crDLMFreeDLM(CRDLM *dlm, SPUDispatchTable *dispatchTable) +{ + /* We're about to change the displayLists hash; lock it first */ + DLM_LOCK(dlm) + + /* Decrement the user count. If the user count has gone to + * 0, then free the rest of the DLM. Otherwise, other + * contexts or threads are still using this DLM; keep + * it around. + */ + dlm->userCount--; + if (dlm->userCount == 0) { + + crFreeHashtableEx(dlm->displayLists, crdlmFreeDisplayListResourcesCb, dispatchTable); + dlm->displayLists = NULL; + + /* Must unlock before freeing the mutex */ + DLM_UNLOCK(dlm) + +#ifdef CHROMIUM_THREADSAFE + /* We release the mutex here; we really should delete the + * thread data key, but there's no utility in Chromium to + * do this. + * + * Note that, should one thread release the entire DLM + * while other threads still believe they are using it, + * any other threads that have current display lists (i.e. + * have issued glNewList more recently than glEndList) + * will be unable to reclaim their (likely very large) + * content buffers, as there will be no way to reclaim + * the thread-specific data. + * + * On the other hand, if one thread really does release + * the DLM while other threads still believe they are + * using it, unreclaimed memory is the least of the + * application's problems... + */ + crFreeMutex(&(dlm->dlMutex)); + + /* We free the TSD key here as well. Note that this will + * strand any threads that still have thread-specific data + * tied to this key; but as stated above, if any threads + * still do have thread-specific data attached to this DLM, + * they're in big trouble anyway. + */ + crFreeTSD(&(dlm->tsdKey)); + crFreeTSD(&CRDLMTSDKey); +#endif + + /* Free the master record, and we're all done. */ + crFree(dlm); + } + else { + /* We're keeping the DLM around for other users. Unlock it, + * but retain its memory and display lists. + */ + DLM_UNLOCK(dlm) + } +} + +/** + * The actual run-time state of a DLM is bound to a context + * (because each context can be used by at most one thread at + * a time, and a thread can only use one context at a time, + * while multiple contexts can use the same DLM). + * This creates the structure required to hold the state, and + * returns it to the caller, who should store it with any other + * context-specific information. + */ + +CRDLMContextState DLM_APIENTRY *crDLMNewContext(CRDLM *dlm) +{ + CRDLMContextState *state; + + /* Get a record for our own internal state structure */ + state = (CRDLMContextState *)crAlloc(sizeof(CRDLMContextState)); + if (!state) { + return NULL; + } + + state->dlm = dlm; + state->currentListIdentifier = 0; + state->currentListInfo = NULL; + state->currentListMode = GL_FALSE; + state->listBase = 0; + + /* Increment the use count of the DLM provided. This guarantees that + * the DLM won't be released until all the contexts have released it. + */ + crDLMUseDLM(dlm); + + return state; +} + + +/** + * This routine should be called when a MakeCurrent changes the current + * context. It sets the thread data (or global data, in an unthreaded + * environment) appropriately; this in turn changes the behavior of + * the installed DLM API functions. + */ +void DLM_APIENTRY crDLMSetCurrentState(CRDLMContextState *state) +{ + CRDLMContextState *currentState = CURRENT_STATE(); + if (currentState != state) { + SET_CURRENT_STATE(state); + } +} + +CRDLMContextState DLM_APIENTRY *crDLMGetCurrentState(void) +{ + return CURRENT_STATE(); +} + +/** + * This routine, of course, is used to release a DLM context when it + * is no longer going to be used. + */ + +void DLM_APIENTRY crDLMFreeContext(CRDLMContextState *state, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + + /* If we're currently using this context, release it first */ + if (listState == state) + crDLMSetCurrentState(NULL); + + /* Try to free the DLM. This will either decrement the use count, + * or will actually free the DLM, if we were the last user. + */ + crDLMFreeDLM(state->dlm, dispatchTable); + state->dlm = NULL; + + /* If any buffers still remain (e.g. because there was an open + * display list), remove those as well. + */ + if (state->currentListInfo) + { + crdlmFreeDisplayListResourcesCb((void *)state->currentListInfo, (void *)dispatchTable); + state->currentListInfo = NULL; + } + state->currentListIdentifier = 0; + + /* Free the state record itself */ + crFree(state); +} + + +/** + * This function can be used if the caller wishes to free up the + * potentially considerable resources used to store the display list + * content, without losing the rest of the display list management. + * For one example, consider an SPU that conditionally sends its + * input stream to multiple servers. It could broadcast all display + * lists to all servers, or it could only send display lists to servers + * that need them. After all servers have the display list, the SPU + * may wish to release the resources used to manage the content. + */ +CRDLMError DLM_APIENTRY crDLMDeleteListContent(CRDLM *dlm, unsigned long listIdentifier) +{ + DLMListInfo *listInfo; + DLMInstanceList *instance; + + listInfo = (DLMListInfo *) crHashtableSearch(dlm->displayLists, listIdentifier); + if (listInfo && (instance = listInfo->first)) { + while (instance) { + DLMInstanceList *nextInstance; + nextInstance = instance->next; + crFree(instance); + instance = nextInstance; + } + listInfo->first = listInfo->last = NULL; + } + return GL_NO_ERROR; +} + +/** + * + * Playback/execute a list. + * dlm - the display list manager context + * listIdentifier - the display list ID (as specified by app) to playback + * dispatchTable - the GL dispatch table to jump through as we execute commands + */ +void DLM_APIENTRY crDLMReplayDLMList(CRDLM *dlm, unsigned long listIdentifier, SPUDispatchTable *dispatchTable) +{ + DLMListInfo *listInfo; + + listInfo = (DLMListInfo *)crHashtableSearch(dlm->displayLists, listIdentifier); + if (listInfo) { + DLMInstanceList *instance = listInfo->first; + while (instance) { + /* mutex, to make sure another thread doesn't change the list? */ + /* For now, leave it alone. */ + (*instance->execute)(instance, dispatchTable); + instance = instance->next; + } + } +} + +/* Playback/execute a list in the current DLM */ +void DLM_APIENTRY crDLMReplayList(unsigned long listIdentifier, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + if (listState) + crDLMReplayDLMList(listState->dlm, listIdentifier, dispatchTable); +} + +/* + * Playback/execute the state changing portions of a list. + * dlm - the display list manager context + * listIdentifier - the display list ID (as specified by app) to playback + * dispatchTable - the GL dispatch table to jump through as we execute commands + */ +void DLM_APIENTRY crDLMReplayDLMListState(CRDLM *dlm, unsigned long listIdentifier, SPUDispatchTable *dispatchTable) +{ + DLMListInfo *listInfo; + + listInfo = (DLMListInfo *)crHashtableSearch(dlm->displayLists, listIdentifier); + if (listInfo) { + DLMInstanceList *instance = listInfo->stateFirst; + while (instance) { + /* mutex, to make sure another thread doesn't change the list? */ + /* For now, leave it alone. */ + (*instance->execute)(instance, dispatchTable); + instance = instance->stateNext; + } + } +} + +void DLM_APIENTRY crDLMReplayListState(unsigned long listIdentifier, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + if (listState) + crDLMReplayDLMListState(listState->dlm, listIdentifier, dispatchTable); +} + +/* This is a switch statement that lists every "type" value valid for a + * glCallLists() function call, with code for decoding the subsequent + * values correctly. It uses the current value of the EXPAND() macro, + * which must expand into an appropriate action to be taken. + * Its codification here allows for multiple uses. + */ +#define CALL_LISTS_SWITCH(type, defaultAction) \ + switch (type) {\ + EXPAND(GL_BYTE, GLbyte *, *p, p++)\ + EXPAND(GL_UNSIGNED_BYTE, GLubyte *, *p, p++)\ + EXPAND(GL_SHORT, GLshort *, *p, p++)\ + EXPAND(GL_UNSIGNED_SHORT, GLushort *, *p, p++)\ + EXPAND(GL_INT, GLint *, *p, p++)\ + EXPAND(GL_FLOAT, GLfloat *, *p, p++)\ + EXPAND(GL_2_BYTES, unsigned char *, 256*p[0] + p[1], p += 2)\ + EXPAND(GL_3_BYTES, unsigned char *, 65536*p[0] + 256*p[1] + p[2], p += 3)\ + EXPAND(GL_4_BYTES, unsigned char *, 16777216*p[0] + 65536*p[1] + 256*p[2] + p[3], p += 4)\ + default:\ + defaultAction;\ + } + +void DLM_APIENTRY crDLMReplayDLMLists(CRDLM *dlm, GLsizei n, GLenum type, const GLvoid * lists, SPUDispatchTable *dispatchTable) +{ + unsigned long listId; + CRDLMContextState *listState = CURRENT_STATE(); + +#define EXPAND(TYPENAME, TYPE, REFERENCE, INCREMENT) \ + case TYPENAME: {\ + TYPE p = (TYPE)lists;\ + while (n--) {\ + listId = listState->listBase + (unsigned long) (REFERENCE);\ + crDLMReplayDLMList(dlm, listId, dispatchTable);\ + INCREMENT;\ + }\ + break;\ + } + + CALL_LISTS_SWITCH(type, break) +#undef EXPAND + +} + +void DLM_APIENTRY crDLMReplayLists(GLsizei n, GLenum type, const GLvoid * lists, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + if (listState) { + crDLMReplayDLMLists(listState->dlm, n, type, lists, dispatchTable); + } +} + +void DLM_APIENTRY crDLMReplayDLMListsState(CRDLM *dlm, GLsizei n, GLenum type, const GLvoid * lists, SPUDispatchTable *dispatchTable) +{ + unsigned long listId; + CRDLMContextState *listState = CURRENT_STATE(); + +#define EXPAND(TYPENAME, TYPE, REFERENCE, INCREMENT) \ + case TYPENAME: {\ + TYPE p = (TYPE)lists;\ + while (n--) {\ + listId = listState->listBase + (unsigned long) (REFERENCE);\ + crDLMReplayDLMListState(dlm, listId, dispatchTable);\ + INCREMENT;\ + }\ + break;\ + } + + CALL_LISTS_SWITCH(type, break) +#undef EXPAND + +} + +void DLM_APIENTRY crDLMReplayListsState(GLsizei n, GLenum type, const GLvoid * lists, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + if (listState) { + crDLMReplayDLMListsState(listState->dlm, n, type, lists, dispatchTable); + } +} + +/* When we compiled the display list, we packed all pixel data + * tightly. When we execute the display list, we have to make + * sure that the client state reflects that the pixel data is + * tightly packed, or it will be interpreted incorrectly. + */ +void DLM_APIENTRY crDLMSetupClientState(SPUDispatchTable *dispatchTable) +{ + dispatchTable->PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + dispatchTable->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + dispatchTable->PixelStorei(GL_UNPACK_SKIP_ROWS, 0); + dispatchTable->PixelStorei(GL_UNPACK_ALIGNMENT, 1); +} + +void DLM_APIENTRY crDLMRestoreClientState(CRClientState *clientState, SPUDispatchTable *dispatchTable) +{ + if (clientState) { + dispatchTable->PixelStorei(GL_UNPACK_ROW_LENGTH, clientState->unpack.rowLength); + dispatchTable->PixelStorei(GL_UNPACK_SKIP_PIXELS, clientState->unpack.skipPixels); + dispatchTable->PixelStorei(GL_UNPACK_SKIP_ROWS, clientState->unpack.skipRows); + dispatchTable->PixelStorei(GL_UNPACK_ALIGNMENT, clientState->unpack.alignment); + } +} + +void DLM_APIENTRY crDLMSendDLMList(CRDLM *dlm, unsigned long listIdentifier, + SPUDispatchTable *dispatchTable) +{ + dispatchTable->NewList(listIdentifier, GL_COMPILE); + crDLMReplayDLMList(dlm, listIdentifier, dispatchTable); + dispatchTable->EndList(); +} + +void DLM_APIENTRY crDLMSendList(unsigned long listIdentifier, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + if (listState) { + crDLMSendDLMList(listState->dlm, listIdentifier, dispatchTable); + } +} + +struct sendListsCallbackParms { + CRDLM *dlm; + SPUDispatchTable *dispatchTable; +}; + +static void sendListsCallback(unsigned long key, void *data, void *dataPtr2) +{ + struct sendListsCallbackParms *parms = (struct sendListsCallbackParms *)dataPtr2; + + crDLMSendDLMList(parms->dlm, key, parms->dispatchTable); +} + +void DLM_APIENTRY crDLMSendAllDLMLists(CRDLM *dlm, SPUDispatchTable *dispatchTable) +{ + struct sendListsCallbackParms parms; + + /* This is how we pass our parameter information to the callback routine - + * through a pointer to this local structure. + */ + parms.dlm = dlm; + parms.dispatchTable = dispatchTable; + + crHashtableWalk(dlm->displayLists, sendListsCallback, (void *)&parms); +} + +void DLM_APIENTRY crDLMSendAllLists(SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + if (listState) { + crDLMSendAllDLMLists(listState->dlm, dispatchTable); + } +} + +/** Another clever callback arrangement to get the desired data. */ +struct getRefsCallbackParms { + int remainingOffset; + int remainingCount; + unsigned int *buffer; + int totalCount; +}; + +/* + * Return id of list currently being compiled. Returns 0 of there's no + * current DLM state, or if no list is being compiled. + */ +GLuint DLM_APIENTRY crDLMGetCurrentList(void) +{ + CRDLMContextState *listState = CURRENT_STATE(); + return listState ? listState->currentListIdentifier : 0; +} + +/* + * Return mode of list currently being compiled. Should be + * GL_FALSE if no list is being compiled, or GL_COMPILE if a + * list is being compiled but not executed, or GL_COMPILE_AND_EXECUTE + * if a list is being compiled and executed. + */ +GLenum DLM_APIENTRY crDLMGetCurrentMode(void) +{ + CRDLMContextState *listState = CURRENT_STATE(); + return listState ? listState->currentListMode : 0; +} + + +static CRDLMErrorCallback ErrorCallback = NULL; + +void DLM_APIENTRY crDLMErrorFunction(CRDLMErrorCallback callback) +{ + ErrorCallback = callback; +} + +void crdlm_error(int line, const char *file, GLenum error, const char *info) +{ + if (ErrorCallback) + (*ErrorCallback)(line, file, error, info); +} diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm.h b/src/VBox/HostServices/SharedOpenGL/dlm/dlm.h new file mode 100644 index 00000000..2e6db46e --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm.h @@ -0,0 +1,31 @@ +/* $Id: dlm.h $ */ + +#ifndef _DLM_H +#define _DLM_H + +#include "cr_dlm.h" +#include "cr_spu.h" + +#ifdef CHROMIUM_THREADSAFE +#define DLM_LOCK(dlm) crLockMutex(&(dlm->dlMutex)); +#define DLM_UNLOCK(dlm) crUnlockMutex(&(dlm->dlMutex)); +extern CRtsd CRDLMTSDKey; +#define SET_CURRENT_STATE(state) crSetTSD(&CRDLMTSDKey, (void *)state); +#define CURRENT_STATE() ((CRDLMContextState *)crGetTSD(&CRDLMTSDKey)) +#else +#define DLM_LOCK(dlm) +#define DLM_UNLOCK(dlm) +extern CRDLMContextState *CRDLMCurrentState; +#define SET_CURRENT_STATE(state) CRDLMCurrentState = (state); +#define CURRENT_STATE() (CRDLMCurrentState) +#endif + +/* These routines are intended to be used within the DLM library, across + * the modules therein, but not as an API into the DLM library from + * outside. + */ +extern void crdlmWarning( int line, char *file, GLenum error, char *format, ... ); +extern void crdlmFreeDisplayListResourcesCb(void *pParm1, void *pParam2); +extern void crdlm_error(int line, const char *file, GLenum error, const char *info); + +#endif diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_arrays.c b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_arrays.c new file mode 100644 index 00000000..d14d7198 --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_arrays.c @@ -0,0 +1,387 @@ +/* $Id: dlm_arrays.c $ */ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include <stdarg.h> +#include "chromium.h" +#include "cr_dlm.h" +#include "dlm.h" + +/* + * XXX this code is awfully similar to the code in arrayspu.c + * We should try to write something reusable. + */ + +void DLM_APIENTRY crDLMCompileArrayElement (GLint index, CRClientState *c) +{ + unsigned char *p; + int unit; + + if (c->array.e.enabled) + { + crDLMCompileEdgeFlagv(c->array.e.p + index*c->array.e.stride); + } + for (unit = 0; unit < CR_MAX_TEXTURE_UNITS; unit++) + { + if (c->array.t[unit].enabled) + { + p = c->array.t[unit].p + index*c->array.t[unit].stride; + switch (c->array.t[unit].type) + { + case GL_SHORT: + switch (c->array.t[c->curClientTextureUnit].size) + { + case 1: crDLMCompileMultiTexCoord1svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; + case 2: crDLMCompileMultiTexCoord2svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; + case 3: crDLMCompileMultiTexCoord3svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; + case 4: crDLMCompileMultiTexCoord4svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; + } + break; + case GL_INT: + switch (c->array.t[c->curClientTextureUnit].size) + { + case 1: crDLMCompileMultiTexCoord1ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; + case 2: crDLMCompileMultiTexCoord2ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; + case 3: crDLMCompileMultiTexCoord3ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; + case 4: crDLMCompileMultiTexCoord4ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; + } + break; + case GL_FLOAT: + switch (c->array.t[c->curClientTextureUnit].size) + { + case 1: crDLMCompileMultiTexCoord1fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; + case 2: crDLMCompileMultiTexCoord2fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; + case 3: crDLMCompileMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; + case 4: crDLMCompileMultiTexCoord4fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; + } + break; + case GL_DOUBLE: + switch (c->array.t[c->curClientTextureUnit].size) + { + case 1: crDLMCompileMultiTexCoord1dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; + case 2: crDLMCompileMultiTexCoord2dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; + case 3: crDLMCompileMultiTexCoord3dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; + case 4: crDLMCompileMultiTexCoord4dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; + } + break; + } + } + } /* loop over texture units */ + + if (c->array.i.enabled) + { + p = c->array.i.p + index*c->array.i.stride; + switch (c->array.i.type) + { + case GL_SHORT: crDLMCompileIndexsv((GLshort *)p); break; + case GL_INT: crDLMCompileIndexiv((GLint *)p); break; + case GL_FLOAT: crDLMCompileIndexfv((GLfloat *)p); break; + case GL_DOUBLE: crDLMCompileIndexdv((GLdouble *)p); break; + } + } + if (c->array.c.enabled) + { + p = c->array.c.p + index*c->array.c.stride; + switch (c->array.c.type) + { + case GL_BYTE: + switch (c->array.c.size) + { + case 3: crDLMCompileColor3bv((GLbyte *)p); break; + case 4: crDLMCompileColor4bv((GLbyte *)p); break; + } + break; + case GL_UNSIGNED_BYTE: + switch (c->array.c.size) + { + case 3: crDLMCompileColor3ubv((GLubyte *)p); break; + case 4: crDLMCompileColor4ubv((GLubyte *)p); break; + } + break; + case GL_SHORT: + switch (c->array.c.size) + { + case 3: crDLMCompileColor3sv((GLshort *)p); break; + case 4: crDLMCompileColor4sv((GLshort *)p); break; + } + break; + case GL_UNSIGNED_SHORT: + switch (c->array.c.size) + { + case 3: crDLMCompileColor3usv((GLushort *)p); break; + case 4: crDLMCompileColor4usv((GLushort *)p); break; + } + break; + case GL_INT: + switch (c->array.c.size) + { + case 3: crDLMCompileColor3iv((GLint *)p); break; + case 4: crDLMCompileColor4iv((GLint *)p); break; + } + break; + case GL_UNSIGNED_INT: + switch (c->array.c.size) + { + case 3: crDLMCompileColor3uiv((GLuint *)p); break; + case 4: crDLMCompileColor4uiv((GLuint *)p); break; + } + break; + case GL_FLOAT: + switch (c->array.c.size) + { + case 3: crDLMCompileColor3fv((GLfloat *)p); break; + case 4: crDLMCompileColor4fv((GLfloat *)p); break; + } + break; + case GL_DOUBLE: + switch (c->array.c.size) + { + case 3: crDLMCompileColor3dv((GLdouble *)p); break; + case 4: crDLMCompileColor4dv((GLdouble *)p); break; + } + break; + } + } + if (c->array.n.enabled) + { + p = c->array.n.p + index*c->array.n.stride; + switch (c->array.n.type) + { + case GL_BYTE: crDLMCompileNormal3bv((GLbyte *)p); break; + case GL_SHORT: crDLMCompileNormal3sv((GLshort *)p); break; + case GL_INT: crDLMCompileNormal3iv((GLint *)p); break; + case GL_FLOAT: crDLMCompileNormal3fv((GLfloat *)p); break; + case GL_DOUBLE: crDLMCompileNormal3dv((GLdouble *)p); break; + } + } +#ifdef CR_EXT_secondary_color + if (c->array.s.enabled) + { + p = c->array.s.p + index*c->array.s.stride; + switch (c->array.s.type) + { + case GL_BYTE: + crDLMCompileSecondaryColor3bvEXT((GLbyte *)p); break; + case GL_UNSIGNED_BYTE: + crDLMCompileSecondaryColor3ubvEXT((GLubyte *)p); break; + case GL_SHORT: + crDLMCompileSecondaryColor3svEXT((GLshort *)p); break; + case GL_UNSIGNED_SHORT: + crDLMCompileSecondaryColor3usvEXT((GLushort *)p); break; + case GL_INT: + crDLMCompileSecondaryColor3ivEXT((GLint *)p); break; + case GL_UNSIGNED_INT: + crDLMCompileSecondaryColor3uivEXT((GLuint *)p); break; + case GL_FLOAT: + crDLMCompileSecondaryColor3fvEXT((GLfloat *)p); break; + case GL_DOUBLE: + crDLMCompileSecondaryColor3dvEXT((GLdouble *)p); break; + } + } +#endif + if (c->array.v.enabled) + { + p = c->array.v.p + (index*c->array.v.stride); + + switch (c->array.v.type) + { + case GL_SHORT: + switch (c->array.v.size) + { + case 2: crDLMCompileVertex2sv((GLshort *)p); break; + case 3: crDLMCompileVertex3sv((GLshort *)p); break; + case 4: crDLMCompileVertex4sv((GLshort *)p); break; + } + break; + case GL_INT: + switch (c->array.v.size) + { + case 2: crDLMCompileVertex2iv((GLint *)p); break; + case 3: crDLMCompileVertex3iv((GLint *)p); break; + case 4: crDLMCompileVertex4iv((GLint *)p); break; + } + break; + case GL_FLOAT: + switch (c->array.v.size) + { + case 2: crDLMCompileVertex2fv((GLfloat *)p); break; + case 3: crDLMCompileVertex3fv((GLfloat *)p); break; + case 4: crDLMCompileVertex4fv((GLfloat *)p); break; + } + break; + case GL_DOUBLE: + switch (c->array.v.size) + { + case 2: crDLMCompileVertex2dv((GLdouble *)p); break; + case 3: crDLMCompileVertex3dv((GLdouble *)p); break; + case 4: crDLMCompileVertex4dv((GLdouble *)p); break; + } + break; + } + } +} + +void DLM_APIENTRY crDLMCompileDrawArrays(GLenum mode, GLint first, GLsizei count, CRClientState *c) +{ + int i; + + if (count < 0) + { + crdlmWarning(__LINE__, __FILE__, GL_INVALID_VALUE, "DLM DrawArrays(negative count)"); + return; + } + + if (mode > GL_POLYGON) + { + crdlmWarning(__LINE__, __FILE__, GL_INVALID_ENUM, "DLM DrawArrays(bad mode)"); + return; + } + + crDLMCompileBegin(mode); + for (i=0; i<count; i++) + { + crDLMCompileArrayElement(first + i, c); + } + crDLMCompileEnd(); +} + +void DLM_APIENTRY crDLMCompileDrawElements(GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices, CRClientState *c) +{ + int i; + GLubyte *p = (GLubyte *)indices; + + if (count < 0) + { + crdlmWarning(__LINE__, __FILE__, GL_INVALID_VALUE, "DLM DrawElements(negative count)"); + return; + } + + if (mode > GL_POLYGON) + { + crdlmWarning(__LINE__, __FILE__, GL_INVALID_ENUM, "DLM DrawElements(bad mode)"); + return; + } + + if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_INT) + { + crdlmWarning(__LINE__, __FILE__, GL_INVALID_ENUM, "DLM DrawElements(bad type)"); + return; + } + + crDLMCompileBegin(mode); + switch (type) + { + case GL_UNSIGNED_BYTE: + for (i=0; i<count; i++) + { + crDLMCompileArrayElement((GLint) *p++, c); + } + break; + case GL_UNSIGNED_SHORT: + for (i=0; i<count; i++) + { + crDLMCompileArrayElement((GLint) * (GLushort *) p, c); + p+=sizeof (GLushort); + } + break; + case GL_UNSIGNED_INT: + for (i=0; i<count; i++) + { + crDLMCompileArrayElement((GLint) * (GLuint *) p, c); + p+=sizeof (GLuint); + } + break; + default: + crError( "this can't happen: DLM DrawElements" ); + break; + } + crDLMCompileEnd(); +} + +void DLM_APIENTRY crDLMCompileDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, + GLenum type, const GLvoid *indices, CRClientState *c) +{ + int i; + GLubyte *p = (GLubyte *)indices; + + (void) end; + + if (count < 0) + { + crdlmWarning(__LINE__, __FILE__, GL_INVALID_VALUE, "DLM DrawRangeElements(negative count)"); + return; + } + + if (mode > GL_POLYGON) + { + crdlmWarning(__LINE__, __FILE__, GL_INVALID_ENUM, "DLM DrawRangeElements(bad mode)"); + return; + } + + if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_INT) + { + crdlmWarning(__LINE__, __FILE__, GL_INVALID_ENUM, "DLM DrawRangeElements(bad type)"); + return; + } + + crDLMCompileBegin(mode); + switch (type) + { + case GL_UNSIGNED_BYTE: + for (i=start; i<count; i++) + { + crDLMCompileArrayElement((GLint) *p++, c); + } + break; + case GL_UNSIGNED_SHORT: + for (i=start; i<count; i++) + { + crDLMCompileArrayElement((GLint) * (GLushort *) p, c); + p+=sizeof (GLushort); + } + break; + case GL_UNSIGNED_INT: + for (i=start; i<count; i++) + { + crDLMCompileArrayElement((GLint) * (GLuint *) p, c); + p+=sizeof (GLuint); + } + break; + default: + crError( "this can't happen: DLM DrawRangeElements" ); + break; + } + crDLMCompileEnd(); +} + +#ifdef CR_EXT_multi_draw_arrays +void DLM_APIENTRY crDLMCompileMultiDrawArraysEXT( GLenum mode, GLint *first, + GLsizei *count, GLsizei primcount, CRClientState *c) +{ + GLint i; + + for (i = 0; i < primcount; i++) { + if (count[i] > 0) { + crDLMCompileDrawArrays(mode, first[i], count[i], c); + } + } +} + + +void DLM_APIENTRY crDLMCompileMultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type, + const GLvoid **indices, GLsizei primcount, CRClientState *c) +{ + GLint i; + + for (i = 0; i < primcount; i++) { + if (count[i] > 0) { + crDLMCompileDrawElements(mode, count[i], type, indices[i], c); + } + } +} +#endif /* CR_EXT_multi_draw_arrays */ diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_checklist.c b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_checklist.c new file mode 100644 index 00000000..e631c02e --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_checklist.c @@ -0,0 +1,51 @@ +/* $Id: dlm_checklist.c $ */ +#include "cr_dlm.h" +#include "cr_mem.h" +#include "cr_pixeldata.h" +#include "cr_string.h" +#include "dlm.h" + +/***************************************************************************** + * These helper functions are used for GL functions that are listed in + * the APIspec.txt file as "checklist", meaning that sometimes they + * represent functions that can be stored in a display list, and sometimes + * they represent control functions that must be executed immediately. + * + * The calling SPU must use these check functions (or their equivalents) + * before asking the DLM to compile any elements of these types. + * They return nonzero (TRUE) if the element goes into a display list. + */ + +int DLM_APIENTRY crDLMCheckListTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + return (target != GL_PROXY_TEXTURE_1D); +} + +int DLM_APIENTRY crDLMCheckListCompressedTexImage1DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imagesize, const GLvoid *data) +{ + return (target != GL_PROXY_TEXTURE_1D); +} +int DLM_APIENTRY crDLMCheckListTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + return (target != GL_PROXY_TEXTURE_2D); +} + +int DLM_APIENTRY crDLMCheckListCompressedTexImage2DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imagesize, const GLvoid *data) +{ + return (target != GL_PROXY_TEXTURE_2D); +} + +int DLM_APIENTRY crDLMCheckListTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + return (target != GL_PROXY_TEXTURE_3D); +} + +int DLM_APIENTRY crDLMCheckListTexImage3DEXT(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + return (target != GL_PROXY_TEXTURE_3D); +} + +int DLM_APIENTRY crDLMCheckListCompressedTexImage3DARB(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imagesize, const GLvoid *data) +{ + return (target != GL_PROXY_TEXTURE_3D); +} diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_error.c b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_error.c new file mode 100644 index 00000000..90590e76 --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_error.c @@ -0,0 +1,56 @@ +/* $Id: dlm_error.c $ */ +#include <stdio.h> +#include <stdarg.h> +#include "chromium.h" +#include "cr_mem.h" +#include "dlm.h" +#include "cr_environment.h" +#include "cr_error.h" + +#define GLCLIENT_LIST_ALLOC 1024 + +void crdlmWarning( int line, char *file, GLenum error, char *format, ... ) +{ + char errstr[8096]; + va_list args; + + if (crGetenv("CR_DEBUG")) { + char *glerr; + va_start( args, format ); + vsprintf( errstr, format, args ); + va_end( args ); + + switch (error) { + case GL_NO_ERROR: + glerr = "GL_NO_ERROR"; + break; + case GL_INVALID_VALUE: + glerr = "GL_INVALID_VALUE"; + break; + case GL_INVALID_ENUM: + glerr = "GL_INVALID_ENUM"; + break; + case GL_INVALID_OPERATION: + glerr = "GL_INVALID_OPERATION"; + break; + case GL_STACK_OVERFLOW: + glerr = "GL_STACK_OVERFLOW"; + break; + case GL_STACK_UNDERFLOW: + glerr = "GL_STACK_UNDERFLOW"; + break; + case GL_OUT_OF_MEMORY: + glerr = "GL_OUT_OF_MEMORY"; + break; + case GL_TABLE_TOO_LARGE: + glerr = "GL_TABLE_TOO_LARGE"; + break; + default: + glerr = "unknown"; + break; + } + + crWarning( "DLM error in %s, line %d: %s: %s\n", + file, line, glerr, errstr ); + } +} diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py new file mode 100755 index 00000000..e5468e2b --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_generated.py @@ -0,0 +1,355 @@ +# $Id: dlm_generated.py $ +import sys, cPickle, re + +sys.path.append( "../glapi_parser" ) +import apiutil + +# A routine that can create call strings from instance names +def InstanceCallString( params ): + output = '' + for index in range(0,len(params)): + if index > 0: + output += ", " + if params[index][0] != '': + output += 'instance->' + params[index][0] + return output + +def GetPointerType(basetype): + words = basetype.split() + if words[0] == 'const': + words = words[1:] + if words[-1].endswith('*'): + words[-1] = words[-1][:-1].strip() + if words[-1] == '': + words = words[:-1] + if words[0] == 'void' or words[0] == 'GLvoid': + words[0] = 'int' + return ' '.join(words) + + +def GetPointerInfo(functionName): + # We'll keep track of all the parameters that require pointers. + # They'll require special handling later. + params = apiutil.Parameters(functionName) + pointers = [] + pointername='' + pointerarg='' + pointertype='' + pointersize=0 + pointercomment='' + + index = 0 + for (name, type, vecSize) in params: + # Watch out for the word "const" (which should be ignored) + # and for types that end in "*" (which are pointers and need + # special treatment) + words = type.split() + if words[-1].endswith('*'): + pointers.append(index) + index += 1 + + # If any argument was a pointer, we need a special pointer data + # array. The pointer data will be stored into this array, and + # references to the array will be generated as parameters. + if len(pointers) == 1: + index = pointers[0] + pointername = params[index][0] + pointerarg = pointername + 'Data' + pointertype = GetPointerType(params[index][1]) + pointersize = params[index][2] + if pointersize == 0: + pointersize = "special" + elif len(pointers) > 1: + pointerarg = 'data'; + pointertype = GetPointerType(params[pointers[0]][1]) + for index in range(1,len(pointers)): + if GetPointerType(params[pointers[index]][1]) != pointertype: + pointertype = 'GLvoid *' + + return (pointers,pointername,pointerarg,pointertype,pointersize,pointercomment) + +def wrap_struct(functionName): + params = apiutil.Parameters(functionName) + argstring = apiutil.MakeDeclarationString(params) + extendedArgstring = argstring + props = apiutil.Properties(functionName) + if "useclient" in props or "pixelstore" in props: + extendedArgstring += ", CRClientState *c" + + # We'll keep track of all the parameters that require pointers. + # They'll require special handling later. + (pointers, pointername, pointerarg, pointertype, pointersize, pointercomment) = GetPointerInfo(functionName) + + # Start writing the header + print 'struct instance%s {' % (functionName) + print ' DLMInstanceList *next;' + print ' DLMInstanceList *stateNext;' + print ' int cbInstance;' + print ' VBoxDLOpCode iVBoxOpCode;' + print ' void (DLM_APIENTRY *execute)(DLMInstanceList *instance, SPUDispatchTable *dispatchTable);' + for (name, type, vecSize) in params: + # Watch out for the word "const" (which should be ignored) + # and for types that end in "*" (which are pointers and need + # special treatment) + words = type.split() + if words[0] == 'const': + words = words[1:] + if words[0] != "void": + print ' %s %s;' % (' '.join(words), name) + + # If any argument was a pointer, we need a special pointer data + # array. The pointer data will be stored into this array, and + # references to the array will be generated as parameters. + if len(pointers) == 1: + if pointersize == None: + print " /* Oh no - pointer parameter %s found, but no pointer class specified and can't guess */" % pointername + else: + if pointersize == 'special': + print ' %s %s[1];%s' % (pointertype, pointerarg, pointercomment) + else: + print ' %s %s[%s];%s' % (pointertype, pointerarg, pointersize,pointercomment) + elif len(pointers) > 1: + print ' %s %s[1];%s' % (pointertype, pointerarg,pointercomment) + + print '};' + + # Pointers only happen with instances + if len(pointers) > 1 or (len(pointers) == 1 and pointersize == 'special'): + print 'int crdlm_pointers_%s(struct instance%s *instance, %s);' % (functionName, functionName, extendedArgstring) + + # See if the GL function must sometimes allow passthrough even + # if the display list is open + if "checklist" in apiutil.ChromiumProps(functionName): + print 'int crdlm_checklist_%s(%s);' % (functionName, argstring) + + return + +def wrap_execute(functionName): + + params = apiutil.Parameters(functionName) + (pointers, _, pointerarg, _, _, _) = GetPointerInfo(functionName) + + print 'static void execute%s(DLMInstanceList *x, SPUDispatchTable *dispatchTable)' % functionName + print '{' + if len(params) > 0: + print ' struct instance%s *instance = (struct instance%s *)x;' % (functionName, functionName) + + if len(pointers) == 1: + print ' instance->%s = instance->%s;' % (params[pointers[0]][0], pointerarg) + + print ' if (dispatchTable->%s != NULL)' % (functionName) + print ' dispatchTable->%s(%s);' % (functionName, InstanceCallString(params)) + print ' else' + print ' crWarning("DLM warning: execute%s called with NULL dispatch entry");' % (functionName) + print '}' + +# These code snippets isolate the code required to add a given instance +# to the display list correctly. They are used during generation, to +# generate correct code, and also to create useful utilities. +def AddInstanceToList(pad): + print '%s/* Add this instance to the current display list. */' % pad + print '%sinstance->next = NULL;' % pad + print '%sinstance->stateNext = NULL;' % pad + print '%sif (!state->currentListInfo->first) {' % pad + print '%s state->currentListInfo->first = (DLMInstanceList *)instance;' % pad + print '%s}' % pad + print '%selse {' % pad + print '%s state->currentListInfo->last->next = (DLMInstanceList *)instance;' % pad + print '%s}' % pad + print '%sstate->currentListInfo->last = (DLMInstanceList *)instance;' % pad + print '%sstate->currentListInfo->numInstances++;' % pad + +def AddInstanceToStateList(pad): + print '%s/* Instances that change state have to be added to the state list as well. */' % pad + print '%sif (!state->currentListInfo->stateFirst) {' % pad + print '%s state->currentListInfo->stateFirst = (DLMInstanceList *)instance;' % pad + print '%s}' % pad + print '%selse {' % pad + print '%s state->currentListInfo->stateLast->stateNext = (DLMInstanceList *)instance;' % pad + print '%s}' % pad + print '%sstate->currentListInfo->stateLast = (DLMInstanceList *)instance;' % pad + + +# The compile wrapper collects the parameters into a DLMInstanceList +# element, and adds that element to the end of the display list currently +# being compiled. +def wrap_compile(functionName): + params = apiutil.Parameters(functionName) + return_type = apiutil.ReturnType(functionName) + # Make sure the return type is void. It's nonsensical to compile + # an element with any other return type. + if return_type != 'void': + print '/* Nonsense: DL function %s has a %s return type?!? */' % (functionName, return_type) + + # Define a structure to hold all the parameters. Note that the + # top parameters must exactly match the DLMInstanceList structure + # in include/cr_dlm.h, or everything will break horribly. + # Start off by getting all the pointer info we could ever use + # from the parameters + (pointers, pointername, pointerarg, pointertype, pointersize, pointercomment) = GetPointerInfo(functionName) + + # Finally, the compile wrapper. This one will diverge strongly + # depending on whether or not there are pointer parameters. + callstring = apiutil.MakeCallString(params) + argstring = apiutil.MakeDeclarationString(params) + props = apiutil.Properties(functionName) + if "useclient" in props or "pixelstore" in props: + callstring += ", c" + argstring += ", CRClientState *c" + print 'void DLM_APIENTRY crDLMCompile%s(%s)' % (functionName, argstring) + print '{' + print ' CRDLMContextState *state = CURRENT_STATE();' + print ' struct instance%s *instance;' % (functionName) + + # The calling SPU is supposed to verify that the element is supposed to be + # compiled before it is actually compiled; typically, this is done based + # on whether a glNewList has been executed more recently than a glEndList. + # But some functions are dual-natured, sometimes being compiled, and sometimes + # being executed immediately. We can check for this here. + if "checklist" in apiutil.ChromiumProps(functionName): + print ' if (crDLMCheckList%s(%s))' % (functionName, apiutil.MakeCallString(params)) + print ' {' + print ' crdlm_error(__LINE__, __FILE__, GL_INVALID_OPERATION,' + print ' "this instance of function %s should not be compiled");' % functionName; + print ' return;' + print ' }' + + if len(pointers) > 1 or pointersize == 'special': + # Pass NULL, to just allocate space + print ' instance = crCalloc(sizeof(struct instance%s) + crdlm_pointers_%s(NULL, %s));' % (functionName, functionName, callstring) + else: + print ' instance = crCalloc(sizeof(struct instance%s));' % (functionName) + print ' if (!instance)' + print ' {' + print ' crdlm_error(__LINE__, __FILE__, GL_OUT_OF_MEMORY,' + print ' "out of memory adding %s to display list");' % (functionName) + print ' return;' + print ' }' + + # Put in the fields that must always exist + print ' instance->execute = execute%s;' % functionName + + # Apply all the simple (i.e. non-pointer) parameters + for index in range(len(params)): + if index not in pointers: + name = params[index][0] + print ' instance->%s = %s;' % (name, name) + + # We need to know instance size in bytes in order to save its state later. + print ' instance->cbInstance = sizeof(struct instance%s);' % functionName + + # Set OPCODE. + print ' instance->iVBoxOpCode = VBOX_DL_OPCODE_%s;' % functionName + + # If there's a pointer parameter, apply it. + if len(pointers) == 1: + + print ' if (%s == NULL)' % (params[pointers[0]][0]) + print ' instance->%s = NULL;' % (params[pointers[0]][0]) + print ' else' + print ' instance->%s = instance->%s;' % (params[pointers[0]][0], pointerarg) + + if pointersize == 'special': + print ' instance->cbInstance += crdlm_pointers_%s(instance, %s);' % (functionName, callstring) + else: + print ' crMemcpy((void *)instance->%s, (void *) %s, %s*sizeof(%s));' % (params[pointers[0]][0], params[pointers[0]][0], pointersize, pointertype) + elif len(pointers) == 2: + # this seems to work + print ' instance->cbInstance += crdlm_pointers_%s(instance, %s);' % (functionName, callstring) + elif len(pointers) > 2: + print "#error don't know how to handle pointer parameters for %s" % (functionName) + + # Add the element to the current display list + AddInstanceToList(' ') + # If the element is a state-changing element, add it to the current state list + if apiutil.SetsTrackedState(functionName): + AddInstanceToStateList(' ') + print '}' + +whichfile=sys.argv[1] +if whichfile == 'headers': + print """#ifndef _DLM_GENERATED_H +#define _DLM_GENERATED_H + +#include <VBoxUhgsmi.h> + +/* DO NOT EDIT. This file is auto-generated by dlm_generated.py. */ +""" +else: + print """#include <stdio.h> +#include "cr_spu.h" +#include "cr_dlm.h" +#include "cr_mem.h" +#include "cr_error.h" +#include "state/cr_statefuncs.h" +#include "dlm.h" +#include "dlm_pointers.h" +#include "dlm_generated.h" + +/* DO NOT EDIT. This file is auto-generated by dlm_generated.py. */ +""" + +# Add in the "add_to_dl" utility function, which will be used by +# external (i.e. non-generated) functions. The utility ensures that +# any external functions that are written for compiling elements +# don't have to be rewritten if the conventions for adding to display +# lists are changed. +print """ +void crdlm_add_to_list( + DLMInstanceList *instance, + void (*executeFunc)(DLMInstanceList *x, SPUDispatchTable *dispatchTable)""" + +if (whichfile == 'headers'): + print ");" +else: + print """) { + CRDLMContextState *state = CURRENT_STATE(); + instance->execute = executeFunc;""" + + # Add in the common code for adding the instance to the display list + AddInstanceToList(" ") + + print '}' + print '' + +# Now generate the functions that won't use the crdlm_add_to_list utility. +# These all directly add their own instances to the current display list +# themselves, without using the crdlm_add_to_list() function. +keys = apiutil.GetDispatchedFunctions(sys.argv[3]+"/APIspec.txt") +for func_name in keys: + if apiutil.CanCompile(func_name): + print "\n/*** %s ***/" % func_name + # Auto-generate an appropriate DL function. First, functions + # that go into the display list but that rely on state will + # have to have their argument strings expanded, to take pointers + # to that appropriate state. + if whichfile == "headers": + wrap_struct(func_name) + elif not apiutil.FindSpecial("dlm", func_name): + wrap_execute(func_name) + wrap_compile(func_name) + + +# Generate mapping between OPCODE and routines to be executed. + +if whichfile == "headers": + # Execute routine prototype needed to add static array of routines. + print '' + print 'struct DLMInstanceList;' + print 'typedef void (*VBoxDLMExecuteFn)(struct DLMInstanceList *instance, SPUDispatchTable *dispatchTable);' + print '' + print 'extern VBoxDLMExecuteFn g_VBoxDLMExecuteFns[VBOX_DL_OPCODE_MAX];' + print '' +else: + print '' + print 'VBoxDLMExecuteFn g_VBoxDLMExecuteFns[] = {' + + for func_name in keys: + if apiutil.CanCompile(func_name) and not apiutil.FindSpecial("dlm", func_name): + print ' execute%s,' % func_name + + print '};' + print '' + +if whichfile == 'headers': + print "#endif /* _DLM_GENERATED_H */" diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_header.py b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_header.py new file mode 100644 index 00000000..f68ccaa0 --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_header.py @@ -0,0 +1,274 @@ +# $Id: dlm_header.py $ +import sys, cPickle, re, os + +sys.path.append( "../glapi_parser" ) +import apiutil + +# mode is "header" or "defs" +mode = sys.argv[1] + +keys = apiutil.GetDispatchedFunctions(sys.argv[3]+"/APIspec.txt") + +# Any new function implemented in the DLM has to have an entry added here. +# Each function has its return type, function name, and parameters provided. +# We'll use these to generate both a header file, and a definition file. +additionalFunctions = [ + ('CRDLM DLM_APIENTRY *', 'crDLMNewDLM', 'unsigned int configSize, const CRDLMConfig *config'), + ('CRDLMContextState DLM_APIENTRY *', 'crDLMNewContext', 'CRDLM *dlm'), + ('void DLM_APIENTRY', 'crDLMFreeContext', 'CRDLMContextState *state, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMUseDLM', 'CRDLM *dlm'), + ('void DLM_APIENTRY','crDLMFreeDLM', 'CRDLM *dlm, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMSetCurrentState', 'CRDLMContextState *state'), + ('CRDLMContextState DLM_APIENTRY *', 'crDLMGetCurrentState', 'void'), + ('void DLM_APIENTRY', 'crDLMSetupClientState', 'SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMRestoreClientState', 'CRClientState *clientState, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMSendAllDLMLists', 'CRDLM *dlm, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMSendAllLists', 'SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMSendDLMList', 'CRDLM *dlm, unsigned long listIdentifier, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMSendList', 'unsigned long listIdentifier, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMReplayDLMList', 'CRDLM *dlm, unsigned long listIdentifier, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMReplayList', 'unsigned long listIdentifier, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMReplayDLMListState', 'CRDLM *dlm, unsigned long listIdentifier, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMReplayListState', 'unsigned long listIdentifier, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMReplayDLMLists', 'CRDLM *dlm, GLsizei n, GLenum type, const GLvoid *lists, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMReplayLists', 'GLsizei n, GLenum type, const GLvoid *lists, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMReplayDLMListsState', 'CRDLM *dlm, GLsizei n, GLenum type, const GLvoid *lists, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMReplayListsState', 'GLsizei n, GLenum type, const GLvoid *lists, SPUDispatchTable *dispatchTable'), + ('CRDLMError DLM_APIENTRY', 'crDLMDeleteListContent', 'CRDLM *dlm, unsigned long listIdentifier'), + ('void DLM_APIENTRY', 'crDLMComputeBoundingBox', 'unsigned long listId'), + ('GLuint DLM_APIENTRY', 'crDLMGetCurrentList', 'void'), + ('GLenum DLM_APIENTRY', 'crDLMGetCurrentMode', 'void'), + ('void DLM_APIENTRY', 'crDLMErrorFunction', 'CRDLMErrorCallback callback'), + ('void DLM_APIENTRY', 'crDLMNewList', 'GLuint list, GLenum mode, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMEndList', 'SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMCallList', 'GLuint list, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMCallLists', 'GLsizei n, GLenum type, const GLvoid *lists, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMDeleteLists', 'GLuint list, GLsizei range, SPUDispatchTable *dispatchTable'), + ('void DLM_APIENTRY', 'crDLMListBase', 'GLuint base, SPUDispatchTable *dispatchTable'), + ('GLboolean DLM_APIENTRY', 'crDLMIsList', 'GLuint list, SPUDispatchTable *dispatchTable'), + ('GLuint DLM_APIENTRY', 'crDLMGenLists', 'GLsizei range, SPUDispatchTable *dispatchTable'), + ('int32_t DLM_APIENTRY', 'crDLMSaveState', 'CRDLM *dlm, PSSMHANDLE pSSM'), + ('bool DLM_APIENTRY', 'crDLMLoadState', 'CRDLM *dlm, PSSMHANDLE pSSM, SPUDispatchTable *dispatchTable'), + #('void DLM_APIENTRY', 'crDLMListSent', 'CRDLM *dlm, unsigned long listIdentifier'), + #('GLboolean DLM_APIENTRY', 'crDLMIsListSent', 'CRDLM *dlm, unsigned long listIdentifier'), + #('GLint DLM_APIENTRY', 'crDLMListSize', 'CRDLM *dlm, unsigned long listIdentifier'), +] + +if mode == 'header': + print """#ifndef CR_DLM_H + +/* DO NOT EDIT. This file is auto-generated by %s. */ +#define CR_DLM_H + +#if defined(WINDOWS) +#define DLM_APIENTRY +#else +#define DLM_APIENTRY +#endif + +#include "chromium.h" +#include "state/cr_client.h" +#include "cr_spu.h" +#include "cr_hash.h" +#include "cr_threads.h" +#include "cr_pack.h" +#ifdef CHROMIUM_THREADSAFE +#include "cr_threads.h" +#endif +#include <VBox/types.h> +""" % 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: + if apiutil.CanCompile(func_name) and not apiutil.FindSpecial("dlm", func_name): + print " VBOX_DL_OPCODE_%s," % func_name + + print " VBOX_DL_OPCODE_MAX," + print "} VBoxDLOpCode;" + + print """ +/* 3D bounding box */ +typedef struct { + double xmin, xmax, ymin, ymax, zmin, zmax; +} CRDLMBounds; + +/* Indicates whether we're currently involved in playback or not */ +typedef enum { + CRDLM_IMMEDIATE = 0, + CRDLM_REPLAY_STATE_FUNCTIONS = 1, + CRDLM_REPLAY_ALL_FUNCTIONS = 2 +} CRDLMReplayState; + +/* This is enough information to hold an instance of a single function call. */ +typedef struct DLMInstanceList { + struct DLMInstanceList *next; + struct DLMInstanceList *stateNext; + 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; + +typedef struct { + DLMInstanceList *first, *last; + uint32_t numInstances; + DLMInstanceList *stateFirst, *stateLast; + GLuint hwid; +} DLMListInfo; + +typedef struct { + /* This holds all the display list information, hashed by list identifier. */ + CRHashTable *displayLists; + + /* This is a count of the number of contexts/users that are using + * this DLM. + */ + unsigned int userCount; + +#ifdef CHROMIUM_THREADSAFE + /* This mutex protects the displayLists hash table from simultaneous + * updates by multiple contexts. + */ + CRmutex dlMutex; + CRtsd tsdKey; +#endif + + /* Configuration information - see the CRDLMConfig structure below + * for details. + */ + unsigned int bufferSize; +} CRDLM; + +/* This structure holds thread-specific state. Each thread can be + * associated with one (and only one) context; and each context can + * be associated with one (and only one) DLM. Making things interesting, + * though, is that each DLM can be associated with multiple contexts. + * + * So the thread-specific data key is associated with each context, not + * with each DLM. Two different threads can, through two different + * contexts that share a single DLM, each have independent state and + * conditions. + */ + +typedef struct { + CRDLM *dlm; /* the DLM associated with this state */ + unsigned long currentListIdentifier; /* open display list */ + DLMListInfo *currentListInfo; /* open display list data */ + GLenum currentListMode; /* GL_COMPILE or GL_COMPILE_AND_EXECUTE */ + GLuint listBase; + +} CRDLMContextState; + +/* These additional structures are for passing information to and from the + * CRDLM interface routines. + */ +typedef struct { + /* The size, in bytes, that the packer will initially allocate for + * each new buffer. + */ +#define CRDLM_DEFAULT_BUFFERSIZE (1024*1024) + unsigned int bufferSize; /* this will be allocated for each buffer */ +} CRDLMConfig; + +/* Positive values match GL error values. + * 0 (GL_NO_ERROR) is returned for success + * Negative values are internal errors. + * Possible positive values (from GL/gl.h) are: + * GL_NO_ERROR (0x0) + * GL_INVALID_ENUM (0x0500) + * GL_INVALID_VALUE (0x0501) + * GL_INVALID_OPERATION (0x0502) + * GL_STACK_OVERFLOW (0x0503) + * GL_STACK_UNDERFLOW (0x0504) + * GL_OUT_OF_MEMORY (0x0505) + */ +typedef int CRDLMError; + +/* This error reported if there's no current state. The caller is responsible + * for appropriately allocating context state with crDLMNewContext(), and + * for making it current with crDLMMakeCurrent(). + */ +#define CRDLM_ERROR_STATE (-1) + + +typedef void (*CRDLMErrorCallback)(int line, const char *file, GLenum error, const char *info); + + +#ifdef __cplusplus +extern "C" { +#endif +""" +elif mode == 'defs': + apiutil.CopyrightDef() + print '''\t; DO NOT EDIT. This code is generated by %s. + +EXPORTS''' % os.path.basename(sys.argv[0]) +else: + raise "unknown generation mode '%s'" % mode + +# Generate the list of functions, starting with those coded into +# the module +for (returnValue, name, parameters) in additionalFunctions: + if mode == 'header': + print "extern %s %s(%s);" % (returnValue, name, parameters) + elif mode == 'defs': + print "%s" % name + +# Continue with functions that are auto-generated. + +if mode == 'header': + print + print "/* auto-generated compilation functions begin here */" + + + +for func_name in keys: + props = apiutil.Properties(func_name) + # We're interested in intercepting all calls that: + # - can be put into a display list (i.e. "not ("nolist" in props)") + # - change client-side state that affects saving DL elements (i.e. "setclient" in props) + + if apiutil.CanCompile(func_name): + params = apiutil.Parameters(func_name) + argstring = apiutil.MakeDeclarationString(params) + if "useclient" in props or "pixelstore" in props: + argstring = argstring + ", CRClientState *c" + + if mode == 'header': + print 'extern void DLM_APIENTRY crDLMCompile%s(%s);' % (func_name, argstring) + elif mode == 'defs': + print "crDLMCompile%s" % func_name + +# Next make declarations for all the checklist functions. +if mode == 'header': + print """ +/* auto-generated CheckList functions begin here. There is one for each + * function that has a dual nature: even when there's an active glNewList, + * sometimes they are compiled into the display list, and sometimes they + * are treated like a control function. The CheckList function will + * return TRUE if the function should really be compiled into a display + * list. The calling SPU is responsible for checking this; but the + * DLM will also print an error if it detects an invalid use. + */ +""" +elif mode == 'defs': + pass + +for func_name in keys: + if "checklist" in apiutil.ChromiumProps(func_name): + params = apiutil.Parameters(func_name) + argstring = apiutil.MakeDeclarationString(params) + if mode == 'header': + print 'int DLM_APIENTRY crDLMCheckList%s(%s);' % (func_name, argstring) + elif mode == 'defs': + print "crDLMCheckList%s" % func_name + +if mode == 'header': + print """ +#ifdef __cplusplus +} +#endif + +#endif /* CR_DLM_H */""" diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_lists.c b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_lists.c new file mode 100644 index 00000000..495819a1 --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_lists.c @@ -0,0 +1,452 @@ +/* $Id: dlm_lists.c $ */ +/** @file + * Implementation of all the Display Lists related routines: + * + * glGenLists, glDeleteLists, glNewList, glEndList, glCallList, glCallLists, + * glListBase and glIsList. + * + * Provide OpenGL IDs mapping between host and guest. + */ + +/* + * Copyright (C) 2015-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include <float.h> +#include "cr_dlm.h" +#include "cr_mem.h" +#include "dlm.h" + + +/** + * Destroy each list entry. + */ +static void crdlmFreeDisplayListElements(DLMInstanceList *instance) +{ + while (instance) + { + DLMInstanceList *nextInstance = instance->next; + crFree(instance); + instance = nextInstance; + } +} + + +/** + * A callback routine used when iterating over all + * available lists in order to remove them. + * + * NOTE: @param pParam2 might be NULL. + */ +void crdlmFreeDisplayListResourcesCb(void *pParm1, void *pParam2) +{ + DLMListInfo *pListInfo = (DLMListInfo *)pParm1; + SPUDispatchTable *dispatchTable = (SPUDispatchTable *)pParam2; + + if (pListInfo) + { + crdlmFreeDisplayListElements(pListInfo->first); + pListInfo->first = pListInfo->last = NULL; + + /* Free host OpenGL resources. */ + if (dispatchTable) + dispatchTable->DeleteLists(pListInfo->hwid, 1); + + crFree(pListInfo); + } +} + + +/** + * Generate host and guest IDs, setup IDs mapping between host and guest. + */ +GLuint DLM_APIENTRY crDLMGenLists(GLsizei range, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + GLuint idHostRangeStart = 0; + GLuint idGuestRangeStart = 0; + + crDebug("DLM: GenLists(%d) (DLM=%p).", range, listState ? listState->dlm : 0); + + if (listState) + { + idHostRangeStart = dispatchTable->GenLists(range); + if (idHostRangeStart > 0) + { + idGuestRangeStart = crHashtableAllocKeys(listState->dlm->displayLists, range); + if (idGuestRangeStart > 0) + { + GLuint i; + bool fSuccess = true; + + /* Now have successfully generated IDs range for host and guest. Let's make IDs association. */ + for (i = 0; i < (GLuint)range; i++) + { + DLMListInfo *pListInfo; + + pListInfo = (DLMListInfo *)crCalloc(sizeof(DLMListInfo)); + if (pListInfo) + { + crMemset(pListInfo, 0, sizeof(DLMListInfo)); + pListInfo->hwid = idHostRangeStart + i; + + /* Insert pre-initialized list data which contains IDs mapping into the hash. */ + crHashtableReplace(listState->dlm->displayLists, idGuestRangeStart + i, pListInfo, NULL); + } + else + { + fSuccess = false; + break; + } + } + + /* All structures allocated and initialized successfully. */ + if (fSuccess) + return idGuestRangeStart; + + /* Rollback some data was not allocated. */ + crDLMDeleteLists(idGuestRangeStart, range, NULL /* we do DeleteLists() later in this routine */ ); + } + else + crDebug("DLM: Can't allocate Display List IDs range for the guest."); + + dispatchTable->DeleteLists(idHostRangeStart, range); + } + else + crDebug("DLM: Can't allocate Display List IDs range on the host side."); + } + else + crDebug("DLM: GenLists(%u) called with no current state.", range); + + /* Can't reserve IDs range. */ + return 0; +} + + +/** + * Release host and guest IDs, free memory resources. + */ +void DLM_APIENTRY crDLMDeleteLists(GLuint list, GLsizei range, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + + crDebug("DLM: DeleteLists(%u, %d) (DLM=%p).", list, range, listState ? listState->dlm : 0); + + if (listState) + { + if (range >= 0) + { + int i; + + /* Free resources: host memory, host IDs and guest IDs. */ + DLM_LOCK(listState->dlm) + for (i = 0; i < range; i++) + crHashtableDeleteEx(listState->dlm->displayLists, list + i, crdlmFreeDisplayListResourcesCb, dispatchTable); + DLM_UNLOCK(listState->dlm) + } + else + crDebug("DLM: DeleteLists(%u, %d) not allowed.", list, range); + } + else + crDebug("DLM: DeleteLists(%u, %d) called with no current state.", list, range); +} + + +/** + * Start recording a list. + */ +void DLM_APIENTRY +crDLMNewList(GLuint list, GLenum mode, SPUDispatchTable *dispatchTable) +{ + DLMListInfo *listInfo; + CRDLMContextState *listState = CURRENT_STATE(); + + crDebug("DLM: NewList(%u, %u) (DLM=%p).", list, mode, listState ? listState->dlm : 0); + + if (listState) + { + /* Valid list ID should be > 0. */ + if (list > 0) + { + if (listState->currentListInfo == NULL) + { + listInfo = (DLMListInfo *)crHashtableSearch(listState->dlm->displayLists, list); + if (listInfo) + { + listInfo->first = listInfo->last = NULL; + listInfo->stateFirst = listInfo->stateLast = NULL; + + listInfo->numInstances = 0; + + listState->currentListInfo = listInfo; + listState->currentListIdentifier = list; + listState->currentListMode = mode; + + dispatchTable->NewList(listInfo->hwid, mode); + + crDebug("DLM: create new list with [guest, host] ID pair [%u, %u].", list, listInfo->hwid); + + return; + } + else + crDebug("DLM: Requested Display List %u was not previously reserved with glGenLists().", list); + } + else + crDebug("DLM: NewList called with display list %u while display list %u was already open.", list, listState->currentListIdentifier); + } + else + crDebug("DLM: NewList called with a list identifier of 0."); + } + else + crDebug("DLM: NewList(%u, %u) called with no current state.\n", list, mode); +} + + +/** + * Stop recording a list. + */ +void DLM_APIENTRY crDLMEndList(SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + + crDebug("DLM: EndList() (DLM=%p).", listState ? listState->dlm : 0); + + if (listState) + { + /* Check if list was ever started. */ + if (listState->currentListInfo) + { + /* reset the current state to show the list had been ended */ + listState->currentListIdentifier = 0; + listState->currentListInfo = NULL; + listState->currentListMode = GL_FALSE; + + dispatchTable->EndList(); + } + else + crDebug("DLM: glEndList() is assuming glNewList() was issued previously."); + } + else + crDebug("DLM: EndList called with no current state."); +} + + +/** + * Execute list on hardware and cach ethis call if we currently recording a list. + */ +void DLM_APIENTRY crDLMCallList(GLuint list, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + + //crDebug("DLM: CallList(%u).", list); + + if (listState) + { + DLMListInfo *listInfo; + + /* Add to calls cache if we recording a list. */ + if (listState->currentListInfo) + crDLMCompileCallList(list); + + /* Find hwid for list. + * We need to take into account listBase: + * - displayLists hash table contains absolute IDs, so we need to add offset in order to resolve guest ID; + * - we also need to substract from hwid in order to execute correct list. */ + listInfo = (DLMListInfo *)crHashtableSearch(listState->dlm->displayLists, list + listState->listBase); + if (listInfo) + dispatchTable->CallList(listInfo->hwid - listState->listBase); + else + crDebug("DLM: CallList(%u) issued for non-existent list.", list); + } + else + crDebug("DLM: CallList(%u) called with no current state.", list); +} + + +/* This routine translates guest Display List IDs in given format to host IDs + * and return resulting IDs as an array of elements of type GL_UNSIGNED_INT. + * It is based on TranslateListIDs() function from crserverlib/server_lists.c. */ +static bool +crDLMConvertListIDs(CRDLMContextState *pListState, GLsizei n, GLenum type, const GLvoid *aGuest, GLuint *aHost) +{ +#define CRDLM_HANDLE_CONVERSION_CASE(_type, _item) \ + { \ + const _type *src = (const _type *)aGuest; \ + for (i = 0; i < n; i++) \ + { \ + GLuint idGuest = (GLuint)(_item) + pListState->listBase; \ + pListInfo = (DLMListInfo *)crHashtableSearch(pListState->dlm->displayLists, idGuest); \ + if (pListInfo) \ + { \ + aHost[i] = pListInfo->hwid - pListState->listBase; \ + } \ + else \ + { \ + crDebug("DLM: CallLists() cannot resolve host list ID for guest ID %u.", idGuest); \ + fSuccess = false; \ + break; \ + } \ + } \ + } + + GLsizei i; + DLMListInfo *pListInfo; + bool fSuccess = true; + + switch (type) + { + case GL_UNSIGNED_BYTE: CRDLM_HANDLE_CONVERSION_CASE(GLubyte, src[i]); break; + case GL_BYTE: CRDLM_HANDLE_CONVERSION_CASE(GLbyte, src[i]); break; + case GL_UNSIGNED_SHORT: CRDLM_HANDLE_CONVERSION_CASE(GLushort, src[i]); break; + case GL_SHORT: CRDLM_HANDLE_CONVERSION_CASE(GLshort, src[i]); break; + case GL_UNSIGNED_INT: CRDLM_HANDLE_CONVERSION_CASE(GLuint, src[i]); break; + case GL_INT: CRDLM_HANDLE_CONVERSION_CASE(GLint, src[i]); break; + case GL_FLOAT: CRDLM_HANDLE_CONVERSION_CASE(GLfloat, src[i]); break; + + case GL_2_BYTES: + { + CRDLM_HANDLE_CONVERSION_CASE(GLubyte, src[i * 2 + 0] * 256 + + src[i * 2 + 1]); + break; + } + + case GL_3_BYTES: + { + CRDLM_HANDLE_CONVERSION_CASE(GLubyte, src[i * 3 + 0] * 256 * 256 + + src[i * 3 + 1] * 256 + + src[i * 3 + 2]); + break; + } + + case GL_4_BYTES: + { + CRDLM_HANDLE_CONVERSION_CASE(GLubyte, src[i * 4 + 0] * 256 * 256 * 256 + + src[i * 4 + 1] * 256 * 256 + + src[i * 4 + 2] * 256 + + src[i * 4 + 3]); + break; + } + + default: + crWarning("DLM: attempt to pass to crDLMCallLists() an unknown type: 0x%x.", type); + } + + return fSuccess; +#undef CRDLM_HANDLE_CONVERSION_CASE +} + + +/** + * Execute lists on hardware and cache this call if we currently recording a list. + */ +void DLM_APIENTRY crDLMCallLists(GLsizei n, GLenum type, const GLvoid *lists, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *pListState = CURRENT_STATE(); + + crDebug("DLM: CallLists(%d, %u, %p).", n, type, lists); + + if (n <= 0 || n >= INT32_MAX / sizeof(GLuint)) + { + crError("crDLMCallLists: parameter 'n' is out of range"); + return; + } + + if (pListState) + { + GLsizei i; + GLuint *aHostIDs; + + /* Add to calls cache if we recording a list. */ + if (pListState->currentListInfo) + crDLMCompileCallLists(n, type, lists); + + aHostIDs = (GLuint *)crAlloc(n * sizeof(GLuint)); + if (aHostIDs) + { + /* Convert IDs. Resulting array contains elements of type of GL_UNSIGNED_INT. */ + if (crDLMConvertListIDs(pListState, n, type, lists, aHostIDs)) + dispatchTable->CallLists(n, GL_UNSIGNED_INT, aHostIDs); + else + crDebug("DLM: CallLists() failed."); + + crFree(aHostIDs); + } + else + crDebug("DLM: no memory on CallLists()."); + } + else + crDebug("DLM: CallLists(%d, %u, %p) called with no current state.", n, type, lists); +} + + +/** + * Set list base, remember its value and add call to the cache. + */ +void DLM_APIENTRY crDLMListBase(GLuint base, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *pListState = CURRENT_STATE(); + + crDebug("DLM: ListBase(%u).", base); + + if (pListState) + { + pListState->listBase = base; + + /* Only add to cache if we are currently recording a list. */ + /** @todo Do we really need to chache it? */ + if (pListState->currentListInfo) + crDLMCompileListBase(base); + + dispatchTable->ListBase(base); + } + else + crDebug("DLM: ListBase(%u) called with no current state.", base); +} + + +/** + * Check if specified list ID belongs to valid Display List. + * Positive result is only returned in case both conditions below are satisfied: + * + * - given list found in DLM hash table (i.e., it was previously allocated + * with crDLMGenLists and still not released with crDLMDeleteLists); + * + * - list is valid on the host side. + */ +GLboolean DLM_APIENTRY crDLMIsList(GLuint list, SPUDispatchTable *dispatchTable) +{ + CRDLMContextState *listState = CURRENT_STATE(); + + crDebug("DLM: IsList(%u).", list); + + if (listState) + { + if (list > 0) + { + DLMListInfo *listInfo = (DLMListInfo *)crHashtableSearch(listState->dlm->displayLists, list); + if (listInfo) + { + if (dispatchTable->IsList(listInfo->hwid)) + return true; + else + crDebug("DLM: list [%u, %u] not found on the host side.", list, listInfo->hwid); + } + else + crDebug("DLM: list %u not found in guest cache.", list); + } + else + crDebug("DLM: IsList(%u) is not allowed.", list); + } + else + crDebug("DLM: IsList(%u) called with no current state.", list); + + return false; +} diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_pointers.c b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_pointers.c new file mode 100644 index 00000000..718ebdec --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_pointers.c @@ -0,0 +1,1125 @@ +/* $Id: dlm_pointers.c $ */ +#include "cr_dlm.h" +#include "cr_mem.h" +#include "cr_pixeldata.h" +#include "cr_string.h" +#include "dlm.h" +#include "dlm_pointers.h" + +/** + * These helper functions are used for GL functions that take a pointers, + * if the size of the arrays that the pointers refer to is not constant. + * These helper functions will determine, on a case-by-case basis, + * how much space is needed to store the array. If the buffer + * parameter is not NULL, they will also pack the data into the given + * array. + * + * Many of the functions included deal with pixel state (Bitmap, DrawPixels, + * etc.). In all these cases, when the function instance is stored in a + * display list, its data is read from memory (as per the parameters + * to PixelStore) and is stored in a tightly packed format (with no + * excess row length, no pixels skipped, no rows, skipped, and a byte + * alignment). + * + * When the instances are executed again, care must be taken to ensure + * that the PixelStore client state that unpacks them is set to reflect + * the tight packing actually used, instead of whatever the current + * client state indicates. + * + * So to do this, client PixelStore state is forced to known values + * before any instances in the display list are executed. The client + * state is then restored to known values afterwards. (The difficulty + * of this is somewhat mollified by the observation that PixelStore + * instances affect client state, and cannot be stored in a display list.) + * + */ + +int crdlm_pointers_Bitmap( struct instanceBitmap *instance, GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap, CRClientState *c) +{ + unsigned int size = ((int)((width + 7) / 8)) * height; + /* glBitmap can be called with a NULL size 0 bitmap, say for + * an empty glyph that only moves the current raster position. + * crMemcpy will raise an exception with a NULL source pointer, even if + * the size to copy is 0. So make sure we don't ram into this. + * Also, the bitmap isn't necessarily just sitting in memory; the PixelStore + * client-side state affects how it is read from memory. It's easiest to just + * use the utility. + */ + if (instance && size > 0) { + crBitmapCopy(width, height, instance->bitmap, bitmap, + &c->unpack); + } + + return size; +} + +int crdlm_pointers_DrawPixels( struct instanceDrawPixels *instance, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ) +{ + unsigned int size = crImageSize(format, type, width, height); + + if (instance && size > 0) { + crPixelCopy2D(width, height, + instance->pixels, format, type, NULL, + pixels, format, type, &c->unpack); + } + + return size; +} +int crdlm_pointers_Fogfv( struct instanceFogfv *instance, GLenum pname, const GLfloat *params ) +{ + unsigned int size = (pname == GL_FOG_COLOR?4:1)*sizeof(GLfloat); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_Fogiv( struct instanceFogiv *instance, GLenum pname, const GLint *params ) +{ + unsigned int size = (pname == GL_FOG_COLOR?4:1)*sizeof(GLint); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_LightModelfv( struct instanceLightModelfv *instance, GLenum pname, const GLfloat *params ) +{ + unsigned int size = (pname == GL_LIGHT_MODEL_AMBIENT?4:1)*sizeof(GLfloat); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_LightModeliv( struct instanceLightModeliv *instance, GLenum pname, const GLint *params ) +{ + unsigned int size = (pname == GL_LIGHT_MODEL_AMBIENT?4:1)*sizeof(GLfloat); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_Lightfv( struct instanceLightfv *instance, GLenum light, GLenum pname, const GLfloat *params ) +{ + unsigned int size; + switch(pname) { + case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: case GL_POSITION: + size = 4 * sizeof(GLfloat); + break; + case GL_SPOT_DIRECTION: + size = 3 * sizeof(GLfloat); + break; + default: + size = 1 * sizeof(GLfloat); + break; + } + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_Lightiv( struct instanceLightiv *instance, GLenum light, GLenum pname, const GLint *params ) +{ + unsigned int size; + switch(pname) { + case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: case GL_POSITION: + size = 4 * sizeof(GLint); + break; + case GL_SPOT_DIRECTION: + size = 3 * sizeof(GLint); + break; + default: + size = 1 * sizeof(GLint); + break; + } + if (instance) crMemcpy(instance->params, params, size); + return size; +} + +/* This utility routine returns the number of components per + * mapping point for all the glMap* functions. + */ +static int map_num_components(GLenum target) +{ + switch(target) { + case GL_MAP1_INDEX: case GL_MAP1_TEXTURE_COORD_1: + return 1; + case GL_MAP1_TEXTURE_COORD_2: + return 2; + case GL_MAP1_VERTEX_3: case GL_MAP1_NORMAL: + case GL_MAP1_TEXTURE_COORD_3: + return 3; + case GL_MAP1_VERTEX_4: case GL_MAP1_COLOR_4: + case GL_MAP1_TEXTURE_COORD_4: + return 4; + + case GL_MAP2_INDEX: case GL_MAP2_TEXTURE_COORD_1: + return 1; + case GL_MAP2_TEXTURE_COORD_2: + return 2; + case GL_MAP2_VERTEX_3: case GL_MAP2_NORMAL: + case GL_MAP2_TEXTURE_COORD_3: + return 3; + case GL_MAP2_VERTEX_4: case GL_MAP2_COLOR_4: + case GL_MAP2_TEXTURE_COORD_4: + return 4; + } + return 0; +} + + +int crdlm_pointers_Map1d( struct instanceMap1d *instance, GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points ) +{ + unsigned int numValues = map_num_components(target); + unsigned int size = order * numValues * sizeof(GLdouble); + if (instance) { + /* This one's a little different - we rearrange the order to + * compress it, and change the instance's stride value to + * match. + */ + const GLdouble *src = points; + GLdouble *dest = instance->points; + register int i; + for (i = 0; i < order; i++) { + crMemcpy(dest, src, numValues * sizeof(GLdouble)); + dest += numValues; + src += stride; + } + + /* We override the stride to show we've compressed the data */ + instance->stride = numValues; + } + return size; +} +int crdlm_pointers_Map1f( struct instanceMap1f *instance, GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points ) +{ + unsigned int numValues = map_num_components(target); + unsigned int size = order * numValues * sizeof(GLfloat); + if (instance) { + /* This one's a little different - we rearrange the order to + * compress it, and change the instance's stride value to + * match. + */ + const GLfloat *src = points; + GLfloat *dest = instance->points; + register int i; + for (i = 0; i < order; i++) { + crMemcpy(dest, src, numValues * sizeof(GLfloat)); + dest += numValues; + src += stride; + } + + /* We override the stride to show we've compressed the data */ + instance->stride = numValues; + } + return size; +} +int crdlm_pointers_Map2d( struct instanceMap2d *instance, GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points ) +{ + unsigned int numValues = map_num_components(target); + unsigned int size = uorder * vorder * numValues * sizeof(GLdouble); + if (instance) { + register int v, u; + const GLdouble *src = points; + GLdouble *dest = instance->points; + for (v = 0; v < vorder; v++) { + for (u = 0; u < uorder; u++) { + crMemcpy(dest, src, numValues * sizeof(GLdouble)); + dest += numValues; + src += ustride; + } + src += vstride - ustride*uorder; + } + /* We override the stride to show we've compressed the data */ + instance->ustride = numValues; + instance->vstride = ustride * uorder; + } + return size; +} +int crdlm_pointers_Map2f( struct instanceMap2f *instance, GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points ) +{ + unsigned int numValues = map_num_components(target); + unsigned int size = uorder * vorder * numValues * sizeof(GLfloat); + if (instance) { + register int v, u; + const GLfloat *src = points; + GLfloat *dest = instance->points; + for (v = 0; v < vorder; v++) { + for (u = 0; u < uorder; u++) { + crMemcpy(dest, src, numValues * sizeof(GLfloat)); + dest += numValues; + src += ustride; + } + src += vstride - ustride*uorder; + } + /* We override the stride to show we've compressed the data */ + instance->ustride = numValues; + instance->vstride = ustride * uorder; + } + return size; +} + +int crdlm_pointers_Materialfv(struct instanceMaterialfv *instance, GLenum face, GLenum pname, const GLfloat *params) +{ + unsigned int size = 0; + switch(pname) { + case GL_AMBIENT_AND_DIFFUSE: + size = 8 * sizeof(GLfloat); + break; + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_EMISSION: + size = 4 * sizeof(GLfloat); + break; + case GL_SHININESS: + size = 1 * sizeof(GLfloat); + break; + case GL_COLOR_INDEXES: + size = 3 * sizeof(GLfloat); + break; + default: + break; + } + if (instance && size > 0) crMemcpy(instance->params, params, size); + return size; +} + +int crdlm_pointers_Materialiv(struct instanceMaterialiv *instance, GLenum face, GLenum pname, const GLint *params) +{ + unsigned int size = 0; + switch(pname) { + case GL_AMBIENT_AND_DIFFUSE: + size = 8 * sizeof(GLint); + break; + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_EMISSION: + size = 4 * sizeof(GLint); + break; + case GL_SHININESS: + size = 1 * sizeof(GLint); + break; + case GL_COLOR_INDEXES: + size = 3 * sizeof(GLint); + break; + default: + break; + } + if (instance && size > 0) crMemcpy(instance->params, params, size); + return size; +} + +int crdlm_pointers_PixelMapfv( struct instancePixelMapfv *instance, GLenum map, GLsizei mapsize, const GLfloat *values ) +{ + unsigned int size = mapsize * sizeof(GLfloat); + if (instance && size > 0) crMemcpy(instance->values, values, size); + return size; +} +int crdlm_pointers_PixelMapuiv( struct instancePixelMapuiv *instance, GLenum map, GLsizei mapsize, const GLuint *values ) +{ + unsigned int size = mapsize * sizeof(GLuint); + if (instance && size > 0) crMemcpy(instance->values, values, size); + return size; +} +int crdlm_pointers_PixelMapusv( struct instancePixelMapusv *instance, GLenum map, GLsizei mapsize, const GLushort *values ) +{ + unsigned int size = mapsize * sizeof(GLushort); + if (instance && size > 0) crMemcpy(instance->values, values, size); + return size; +} + +int crdlm_pointers_PointParameterfvARB( struct instancePointParameterfvARB *instance, GLenum pname, const GLfloat *params) +{ + unsigned int size = 0; + switch(pname) { + case GL_POINT_DISTANCE_ATTENUATION_ARB: + size = 3 * sizeof(GLfloat); + break; + default: + size = 1 * sizeof(GLfloat); + break; + } + return size; +} + +int crdlm_pointers_PointParameteriv( struct instancePointParameteriv *instance, GLenum pname, const GLint *params) +{ + unsigned int size = 0; + switch(pname) { + case GL_POINT_DISTANCE_ATTENUATION_ARB: + size = 3 * sizeof(GLint); + break; + default: + size = 1 * sizeof(GLint); + break; + } + return size; +} + +int crdlm_pointers_TexEnvfv( struct instanceTexEnvfv *instance, GLenum target, GLenum pname, const GLfloat *params ) +{ + unsigned int size = (pname == GL_TEXTURE_ENV_COLOR?4:1)*sizeof(GLfloat); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_TexEnviv( struct instanceTexEnviv *instance, GLenum target, GLenum pname, const GLint *params ) +{ + unsigned int size = (pname == GL_TEXTURE_ENV_COLOR?4:1)*sizeof(GLint); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_TexGendv( struct instanceTexGendv *instance, GLenum coord, GLenum pname, const GLdouble *params ) +{ + unsigned int size = (pname == GL_OBJECT_PLANE||pname==GL_EYE_PLANE?4:1)*sizeof(GLdouble); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_TexGenfv( struct instanceTexGenfv *instance, GLenum coord, GLenum pname, const GLfloat *params ) +{ + unsigned int size = (pname == GL_OBJECT_PLANE||pname==GL_EYE_PLANE?4:1)*sizeof(GLfloat); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_TexGeniv( struct instanceTexGeniv *instance, GLenum coord, GLenum pname, const GLint *params ) +{ + unsigned int size = (pname == GL_OBJECT_PLANE||pname==GL_EYE_PLANE?4:1)*sizeof(GLint); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_TexImage1D( struct instanceTexImage1D *instance, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ) +{ + unsigned int size = crImageSize(format, type, width, 1); + + if (instance && size > 0) { + crPixelCopy1D(instance->pixels, format, type, + pixels, format, type, width, &c->unpack); + } + + return size; +} +int crdlm_pointers_CompressedTexImage1DARB(struct instanceCompressedTexImage1DARB *instance, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imagesize, const GLvoid *data) +{ + unsigned int size = imagesize; + + if (instance && size > 0) { + crMemcpy(instance->data, data, size); + } + + return size; +} + +int crdlm_pointers_TexImage2D( struct instanceTexImage2D *instance, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ) +{ + unsigned int size = crImageSize(format, type, width, height); + + if (instance && size > 0) { + crPixelCopy2D(width, height, + instance->pixels, format, type, NULL, + pixels, format, type, &c->unpack); + } + + return size; +} +int crdlm_pointers_CompressedTexImage2DARB(struct instanceCompressedTexImage2DARB *instance, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imagesize, const GLvoid *data) +{ + unsigned int size = imagesize; + + if (instance && size > 0) { + crMemcpy(instance->data, data, size); + } + + return size; +} + +int crdlm_pointers_TexImage3D( struct instanceTexImage3D *instance, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ) +{ + unsigned int size; + int is_distrib = ((type == GL_TRUE) || (type == GL_FALSE)); + + if (pixels == NULL) { + size = 0; + } + else if (is_distrib) { + size = crStrlen(pixels) + 1 + (type==GL_TRUE?width*height*3:0); + } + else { + size = crTextureSize(format, type, width, height, depth); + } + + if (instance && size > 0) { + if (is_distrib) { + crMemcpy(instance->pixels, pixels, size); + } + else { + crPixelCopy3D(width, height, depth, + instance->pixels, format, type, NULL, + pixels, format, type, &c->unpack); + } + } + + return size; +} +int crdlm_pointers_TexImage3DEXT( struct instanceTexImage3DEXT *instance, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ) +{ + unsigned int size; + int is_distrib = ((type == GL_TRUE) || (type == GL_FALSE)); + + if (pixels == NULL) { + size = 0; + } + else if (is_distrib) { + size = crStrlen(pixels) + 1 + (type==GL_TRUE?width*height*3:0); + } + else { + size = crTextureSize(format, type, width, height, depth); + } + + if (instance && size > 0) { + if (is_distrib) { + crMemcpy(instance->pixels, pixels, size); + } + else { + crPixelCopy3D(width, height, depth, + instance->pixels, format, type, NULL, + pixels, format, type, &c->unpack); + } + } + + return size; +} + +int crdlm_pointers_CompressedTexImage3DARB(struct instanceCompressedTexImage3DARB *instance, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imagesize, const GLvoid *data) +{ + unsigned int size = imagesize; + + if (instance && size > 0) { + crMemcpy(instance->data, data, size); + } + + return size; +} + +int crdlm_pointers_TexParameterfv( struct instanceTexParameterfv *instance, GLenum target, GLenum pname, const GLfloat *params ) +{ + unsigned int size = (pname == GL_TEXTURE_BORDER_COLOR?4:1)*sizeof(GLfloat); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_TexParameteriv( struct instanceTexParameteriv *instance, GLenum target, GLenum pname, const GLint *params ) +{ + unsigned int size = (pname == GL_TEXTURE_BORDER_COLOR?4:1)*sizeof(GLfloat); + if (instance) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_TexSubImage1D( struct instanceTexSubImage1D *instance, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ) +{ + unsigned int size = crImageSize(format, type, width, 1); + + if (instance && size > 0) { + crPixelCopy1D(instance->pixels, format, type, + pixels, format, type, width, &c->unpack); + } + + return size; +} +int crdlm_pointers_TexSubImage2D( struct instanceTexSubImage2D *instance, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ) +{ + unsigned int size = crImageSize(format, type, width, height); + + if (instance && size > 0) { + crPixelCopy2D(width, height, + instance->pixels, format, type, NULL, + pixels, format, type, &c->unpack); + } + + return size; +} +int crdlm_pointers_TexSubImage3D( struct instanceTexSubImage3D *instance, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ) +{ + unsigned int size; + int is_distrib = ((type == GL_TRUE) || (type == GL_FALSE)); + + if (pixels == NULL) { + size = 0; + } + else if (is_distrib) { + size = crStrlen(pixels) + 1 + (type==GL_TRUE?width*height*3:0); + } + else { + size = crTextureSize(format, type, width, height, depth); + } + + if (instance && size > 0) { + if (is_distrib) { + crMemcpy(instance->pixels, pixels, size); + } + else { + crPixelCopy3D(width, height, depth, + instance->pixels, format, type, NULL, + pixels, format, type, &c->unpack); + } + } + + return size; +} + +int crdlm_pointers_CompressedTexSubImage1DARB(struct instanceCompressedTexSubImage1DARB *instance, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imagesize, const GLvoid *data) +{ + unsigned int size = imagesize; + + if (instance && size > 0) { + crMemcpy(instance->data, data, size); + } + + return size; +} + +int crdlm_pointers_CompressedTexSubImage2DARB(struct instanceCompressedTexSubImage2DARB *instance, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imagesize, const GLvoid *data) +{ + unsigned int size = imagesize; + + if (instance && size > 0) { + crMemcpy(instance->data, data, size); + } + + return size; +} +int crdlm_pointers_CompressedTexSubImage3DARB(struct instanceCompressedTexSubImage3DARB *instance, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imagesize, const GLvoid *data) +{ + unsigned int size = imagesize; + + if (instance && size > 0) { + crMemcpy(instance->data, data, size); + } + + return size; +} + +int crdlm_pointers_Rectdv(struct instanceRectdv *instance, const GLdouble *v1, const GLdouble *v2) +{ + unsigned int size = 4 * sizeof(GLdouble); + if (instance) { + instance->data[0] = v1[0]; + instance->data[1] = v1[1]; + instance->data[2] = v2[0]; + instance->data[3] = v2[1]; + instance->v1 = &instance->data[0]; + instance->v2 = &instance->data[2]; + } + return size; +} +int crdlm_pointers_Rectfv(struct instanceRectfv *instance, const GLfloat *v1, const GLfloat *v2) +{ + unsigned int size = 4 * sizeof(GLfloat); + if (instance) { + instance->data[0] = v1[0]; + instance->data[1] = v1[1]; + instance->data[2] = v2[0]; + instance->data[3] = v2[1]; + instance->v1 = &instance->data[0]; + instance->v2 = &instance->data[2]; + } + return size; +} +int crdlm_pointers_Rectiv(struct instanceRectiv *instance, const GLint *v1, const GLint *v2) +{ + unsigned int size = 4 * sizeof(GLint); + if (instance) { + instance->data[0] = v1[0]; + instance->data[1] = v1[1]; + instance->data[2] = v2[0]; + instance->data[3] = v2[1]; + instance->v1 = &instance->data[0]; + instance->v2 = &instance->data[2]; + } + return size; +} +int crdlm_pointers_Rectsv(struct instanceRectsv *instance, const GLshort *v1, const GLshort *v2) +{ + unsigned int size = 4 * sizeof(GLshort); + if (instance) { + instance->data[0] = v1[0]; + instance->data[1] = v1[1]; + instance->data[2] = v2[0]; + instance->data[3] = v2[1]; + instance->v1 = &instance->data[0]; + instance->v2 = &instance->data[2]; + } + return size; +} + +int crdlm_pointers_PrioritizeTextures(struct instancePrioritizeTextures *instance, GLsizei n, const GLuint *textures, const GLclampf *priorities) +{ + unsigned int size = n * (sizeof(GLuint) + sizeof(GLclampf)); + if (instance) { + instance->textures = (GLuint *)&instance->data[0]; + instance->priorities = (GLclampf *)(((char *)&instance->data[0]) + n * sizeof(GLuint)); + if (size > 0) { + crMemcpy(instance->textures, textures, n * sizeof(GLuint)); + crMemcpy(instance->priorities, priorities, n * sizeof(GLclampf)); + } + } + + return size; +} + +static int combiner_num_components(GLenum pname) +{ + switch(pname) { + case GL_CONSTANT_COLOR0_NV: + case GL_CONSTANT_COLOR1_NV: + return 4; + case GL_NUM_GENERAL_COMBINERS_NV: + case GL_COLOR_SUM_CLAMP_NV: + return 1; + } + return 0; +} +int crdlm_pointers_CombinerParameterivNV(struct instanceCombinerParameterivNV *instance, GLenum pname, const GLint *params) +{ + unsigned int size = combiner_num_components(pname) * sizeof(GLint); + if (instance && size > 0) crMemcpy(instance->params, params, size); + return size; +} +int crdlm_pointers_CombinerParameterfvNV(struct instanceCombinerParameterfvNV *instance, GLenum pname, const GLfloat *params) +{ + unsigned int size = combiner_num_components(pname) * sizeof(GLfloat); + if (instance && size > 0) crMemcpy(instance->params, params, size); + return size; +} + +static int combinerstage_num_components(GLenum pname) +{ + switch(pname) { + case GL_CONSTANT_COLOR0_NV: + case GL_CONSTANT_COLOR1_NV: + return 4; + } + return 0; +} +int crdlm_pointers_CombinerStageParameterfvNV(struct instanceCombinerStageParameterfvNV *instance, GLenum stage, GLenum pname, const GLfloat *params) +{ + unsigned int size = combinerstage_num_components(pname) * sizeof(GLfloat); + if (instance && size > 0) crMemcpy(instance->params, params, size); + return size; +} + +static int program_num_components(GLenum target) +{ + switch(target) { + case GL_VERTEX_STATE_PROGRAM_NV: + return 4; + } + return 0; +} +int crdlm_pointers_ExecuteProgramNV(struct instanceExecuteProgramNV *instance, GLenum target, GLuint id, const GLfloat *params) +{ + unsigned int size = program_num_components(target) * sizeof(GLfloat); + if (instance && size > 0) crMemcpy(instance->params, params, size); + return size; +} + +int crdlm_pointers_RequestResidentProgramsNV(struct instanceRequestResidentProgramsNV *instance, GLsizei n, const GLuint *ids) +{ + unsigned int size = 4*sizeof(GLuint); + if (instance && size > 0) crMemcpy(instance->ids, ids, size); + return size; +} + +int crdlm_pointers_LoadProgramNV(struct instanceLoadProgramNV *instance, GLenum target, GLuint id, GLsizei len, const GLubyte *program) +{ + unsigned int size = len*sizeof(GLubyte); + if (instance && size > 0) crMemcpy(instance->program, program, size); + return size; +} + +int crdlm_pointers_ProgramNamedParameter4dNV(struct instanceProgramNamedParameter4dNV *instance, GLuint id, GLsizei len, const GLubyte * name, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + unsigned int size = len * sizeof(GLubyte); + /* XXX */ + return size; +} + +int crdlm_pointers_ProgramNamedParameter4dvNV(struct instanceProgramNamedParameter4dvNV *instance, GLuint id, GLsizei len, const GLubyte * name, const GLdouble * v) +{ + unsigned int size = len * sizeof(GLubyte); + /* XXX */ + return size; +} + +int crdlm_pointers_ProgramNamedParameter4fNV(struct instanceProgramNamedParameter4fNV *instance, GLuint id, GLsizei len, const GLubyte * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + unsigned int size = len * sizeof(GLubyte); + /* XXX */ + return size; +} + +int crdlm_pointers_ProgramNamedParameter4fvNV(struct instanceProgramNamedParameter4fvNV *instance, GLuint id, GLsizei len, const GLubyte * name, const GLfloat * v) +{ + unsigned int size = len * sizeof(GLubyte); + /* XXX */ + return size; +} + +int crdlm_pointers_ProgramStringARB(struct instanceProgramStringARB *instance, GLenum target, GLenum format, GLsizei len, const GLvoid * string) +{ + unsigned int size = len*sizeof(GLubyte); + if (instance && size > 0) crMemcpy(instance->string, string, size); + return size; +} + +int crdlm_pointers_CallLists(struct instanceCallLists *instance, GLsizei n, GLenum type, const GLvoid *lists ) +{ + unsigned int size; + switch (type) { + case GL_BYTE: + size = sizeof(GLbyte); + break; + case GL_UNSIGNED_BYTE: + size = sizeof(GLubyte); + break; + case GL_SHORT: + size = sizeof(GLshort); + break; + case GL_UNSIGNED_SHORT: + size = sizeof(GLushort); + break; + case GL_INT: + size = sizeof(GLint); + break; + case GL_UNSIGNED_INT: + size = sizeof(GLuint); + break; + case GL_FLOAT: + size = sizeof(GLfloat); + break; + case GL_2_BYTES: + size = 2 * sizeof(GLbyte); + break; + case GL_3_BYTES: + size = 3 * sizeof(GLbyte); + break; + case GL_4_BYTES: + size = 4 * sizeof(GLbyte); + break; + default: + size = 0; + } + size *= n; + if (instance && size > 0) crMemcpy(instance->lists, lists, size); + return size; +} + + +int crdlm_pointers_VertexAttribs1dvNV(struct instanceVertexAttribs1dvNV *instance, GLuint index, GLsizei n, const GLdouble *v) +{ + return 1 * n * sizeof(GLdouble); +} + +int crdlm_pointers_VertexAttribs1fvNV(struct instanceVertexAttribs1fvNV *instance, GLuint index, GLsizei n, const GLfloat *v) +{ + return 1 * n * sizeof(GLfloat); +} + +int crdlm_pointers_VertexAttribs1svNV(struct instanceVertexAttribs1svNV *instance, GLuint index, GLsizei n, const GLshort *v) +{ + return 1 * n * sizeof(GLshort); +} + +int crdlm_pointers_VertexAttribs2dvNV(struct instanceVertexAttribs2dvNV *instance, GLuint index, GLsizei n, const GLdouble *v) +{ + return 2 * n * sizeof(GLdouble); +} + +int crdlm_pointers_VertexAttribs2fvNV(struct instanceVertexAttribs2fvNV *instance, GLuint index, GLsizei n, const GLfloat *v) +{ + return 2 * n * sizeof(GLfloat); +} + +int crdlm_pointers_VertexAttribs2svNV(struct instanceVertexAttribs2svNV *instance, GLuint index, GLsizei n, const GLshort *v) +{ + return 2 * n * sizeof(GLshort); +} + +int crdlm_pointers_VertexAttribs3dvNV(struct instanceVertexAttribs3dvNV *instance, GLuint index, GLsizei n, const GLdouble *v) +{ + return 3 * n * sizeof(GLdouble); +} + +int crdlm_pointers_VertexAttribs3fvNV(struct instanceVertexAttribs3fvNV *instance, GLuint index, GLsizei n, const GLfloat *v) +{ + return 3 * n * sizeof(GLfloat); +} + +int crdlm_pointers_VertexAttribs3svNV(struct instanceVertexAttribs3svNV *instance, GLuint index, GLsizei n, const GLshort *v) +{ + return 3 * n * sizeof(GLshort); +} + +int crdlm_pointers_VertexAttribs4dvNV(struct instanceVertexAttribs4dvNV *instance, GLuint index, GLsizei n, const GLdouble *v) +{ + return 4 * n * sizeof(GLdouble); +} + +int crdlm_pointers_VertexAttribs4fvNV(struct instanceVertexAttribs4fvNV *instance, GLuint index, GLsizei n, const GLfloat *v) +{ + return 4 * n * sizeof(GLfloat); +} + +int crdlm_pointers_VertexAttribs4svNV(struct instanceVertexAttribs4svNV *instance, GLuint index, GLsizei n, const GLshort *v) +{ + return 4 * n * sizeof(GLshort); +} + +int crdlm_pointers_VertexAttribs4ubvNV(struct instanceVertexAttribs4ubvNV *instance, GLuint index, GLsizei n, const GLubyte *v) +{ + return 4 * n * sizeof(GLubyte); +} + +int crdlm_pointers_ZPixCR( struct instanceZPixCR *instance, GLsizei width, + GLsizei height, GLenum format, GLenum type, + GLenum ztype, GLint zparm, GLint length, + const GLvoid *pixels, CRClientState *c) +{ + unsigned int size = length; + if (instance && size > 0) { + crMemcpy(instance->pixels,pixels,length); + } + + return size; +} + + +/* + * Prototypes for functions below are auto-generated and definded at out/<os.arch>/<build type>/obj/VBoxOGLgen/dlm_generated.h. + * + * All non-pointer structure fields are already assifned to *instance in out/<os.arch>/<build type>/obj/VBoxOGLgen/dlm_generated.c. + * Here we need to specify the additional size which is required to store data from pointers. + * This size will be added to sizeof(*instance) when dlm_generated.c will dynamically allocate memory for it. Also, + * data from pointers shouls be copied to *instance in case if instance != NULL. Each of functions below is called + * twice from dlm_generated.c: + * - first time with instance = NULL in order to get actual size of data provided by pointer + * - the second time with valid instance in order to copy data into it. + */ + +int crdlm_pointers_BindAttribLocation(struct instanceBindAttribLocation *instance, GLuint program, GLuint index, const char * name) +{ + int cbExtraSpace = (name ? crStrlen(name) + 1 : 0); + if (instance && name && cbExtraSpace) + { + crMemcpy(instance->name, name, cbExtraSpace); + } + + return cbExtraSpace; +} + +int crdlm_pointers_DeleteFramebuffersEXT(struct instanceDeleteFramebuffersEXT *instance, GLsizei n, const GLuint * framebuffers) +{ + int cbExtraSpace = n * sizeof(GLuint); + + if (instance && framebuffers && cbExtraSpace) + crMemcpy(instance->framebuffers, framebuffers, cbExtraSpace); + + return cbExtraSpace; +} + +int crdlm_pointers_DeleteRenderbuffersEXT(struct instanceDeleteRenderbuffersEXT *instance, GLsizei n, const GLuint * renderbuffers) +{ + int cbExtraSpace = n * sizeof(GLuint); + + if (instance && renderbuffers && cbExtraSpace) + crMemcpy(instance->renderbuffers, renderbuffers, cbExtraSpace); + + return cbExtraSpace; +} + +int crdlm_pointers_DrawBuffers(struct instanceDrawBuffers *instance, GLsizei n, const GLenum* bufs) +{ + int cbExtraSpace = n * sizeof(GLenum); + + if (instance && bufs && cbExtraSpace) + crMemcpy(instance->bufs, bufs, cbExtraSpace); + + return cbExtraSpace; +} + +int crdlm_pointers_ShaderSource(struct instanceShaderSource *instance, GLuint shader, GLsizei count, const char ** string, const GLint * length) +{ + int cbExtraSpace = 0; + int cbStrings = 0; + int cbLenghts = 0; + int i; + + /* Calculate reported source code size. */ + if (length && count) + for (i = 0; i < count; i++) + cbStrings += length[i] + /* termination character */ 1; + + /* Calculate size of the rest of parameters. */ + cbLenghts = count * sizeof(GLint); + + /* Resulting size is a summ. */ + cbExtraSpace = cbStrings + cbLenghts; + + /* Copy data if requested. */ + if (instance) + { + if (string && *string && cbStrings) + crMemcpy(instance->string, *string, cbStrings); + if (length && cbLenghts) + crMemcpy(instance->length, length, cbLenghts); + } + + return cbExtraSpace; +} + +int crdlm_pointers_StringMarkerGREMEDY(struct instanceStringMarkerGREMEDY *instance, GLsizei len, const GLvoid* string) +{ + /* @param len assumed to indicate string lenght in bytes. No termination character assumed. */ + int cbExtraSpace = (string && len) ? len : 0; + + if (instance && string && cbExtraSpace) + crMemcpy(instance->string, string, cbExtraSpace); + + return cbExtraSpace; +} + +/* Simplify things a bit. Use this macro instead of copy/paste to similar functions. */ +#define _VBOX_crdlm_pointers_UniformX(_uniformType) \ + int cbExtraSpace = count * sizeof(_uniformType); \ + if (instance && cbExtraSpace && value) \ + crMemcpy(instance->value, value, cbExtraSpace); \ + return cbExtraSpace; + +int crdlm_pointers_Uniform1fv(struct instanceUniform1fv *instance, GLint location, GLsizei count, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformX(GLfloat); +} + +int crdlm_pointers_Uniform1iv(struct instanceUniform1iv *instance, GLint location, GLsizei count, const GLint * value) +{ + _VBOX_crdlm_pointers_UniformX(GLint); +} + +int crdlm_pointers_Uniform2fv(struct instanceUniform2fv *instance, GLint location, GLsizei count, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformX(GLfloat); +} + +int crdlm_pointers_Uniform2iv(struct instanceUniform2iv *instance, GLint location, GLsizei count, const GLint * value) +{ + _VBOX_crdlm_pointers_UniformX(GLint); +} + +int crdlm_pointers_Uniform3fv(struct instanceUniform3fv *instance, GLint location, GLsizei count, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformX(GLfloat); +} + +int crdlm_pointers_Uniform3iv(struct instanceUniform3iv *instance, GLint location, GLsizei count, const GLint * value) +{ + _VBOX_crdlm_pointers_UniformX(GLint); +} + +int crdlm_pointers_Uniform4fv(struct instanceUniform4fv *instance, GLint location, GLsizei count, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformX(GLfloat); +} + +int crdlm_pointers_Uniform4iv(struct instanceUniform4iv *instance, GLint location, GLsizei count, const GLint * value) +{ + _VBOX_crdlm_pointers_UniformX(GLint); +} + +#undef crdlm_pointers_Uniform4iv + +/* Now do the same for UniformMatrix. */ +#define _VBOX_crdlm_pointers_UniformMatrixX(_uniformMatrixType) \ + int cbExtraSpace = count * sizeof(_uniformMatrixType); \ + if (instance && value && cbExtraSpace) \ + crMemcpy(instance->value, value, cbExtraSpace); \ + return cbExtraSpace; + +int crdlm_pointers_UniformMatrix2fv(struct instanceUniformMatrix2fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +int crdlm_pointers_UniformMatrix2x3fv(struct instanceUniformMatrix2x3fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +int crdlm_pointers_UniformMatrix2x4fv(struct instanceUniformMatrix2x4fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +int crdlm_pointers_UniformMatrix3fv(struct instanceUniformMatrix3fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +int crdlm_pointers_UniformMatrix3x2fv(struct instanceUniformMatrix3x2fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +int crdlm_pointers_UniformMatrix3x4fv(struct instanceUniformMatrix3x4fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +int crdlm_pointers_UniformMatrix4fv(struct instanceUniformMatrix4fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +int crdlm_pointers_UniformMatrix4x2fv(struct instanceUniformMatrix4x2fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +int crdlm_pointers_UniformMatrix4x3fv(struct instanceUniformMatrix4x3fv *instance, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) +{ + _VBOX_crdlm_pointers_UniformMatrixX(GLfloat); +} + +#undef _VBOX_crdlm_pointers_UniformMatrixX + +#if 0 +VBoxConCreate +VBoxCreateContext +VBoxPackSetInjectThread +VBoxPresentComposition +VBoxWindowCreate +#endif + +int crdlm_pointers_VBoxConCreate(struct instanceVBoxConCreate *instance, struct VBOXUHGSMI * pHgsmi) +{ + CRASSERT(0); + return 0; +} + +int crdlm_pointers_VBoxCreateContext(struct instanceVBoxCreateContext *instance, GLint con, const char * dpyName, GLint visual, GLint shareCtx) +{ + int cbExtraSpace = (dpyName ? crStrlen(dpyName) + 1 : 0); + + if (instance && dpyName && cbExtraSpace) + crMemcpy(instance->dpyName, dpyName, cbExtraSpace); + + return cbExtraSpace; +} + +int crdlm_pointers_VBoxPackSetInjectThread(struct instanceVBoxPackSetInjectThread *instance, struct VBOXUHGSMI * pHgsmi) +{ + CRASSERT(0); + return 0; +} + +int crdlm_pointers_VBoxPresentComposition(struct instanceVBoxPresentComposition *instance, GLint win, + const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY * pChangedEntry) +{ + CRASSERT(0); + return 0; +} + +int crdlm_pointers_VBoxWindowCreate(struct instanceVBoxWindowCreate *instance, GLint con, const char * dpyName, GLint visBits) +{ + int cbExtraSpace = (dpyName ? crStrlen(dpyName) + 1 : 0); + + if (instance && dpyName && cbExtraSpace) + crMemcpy(instance->dpyName, dpyName, cbExtraSpace); + + return cbExtraSpace; +} diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_pointers.h b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_pointers.h new file mode 100644 index 00000000..51ac2085 --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_pointers.h @@ -0,0 +1,81 @@ +/* $Id: dlm_pointers.h $ */ +#include <VBoxUhgsmi.h> + +#include "cr_dlm.h" +#include "dlm_generated.h" + +#ifndef _DLM_POINTERS_H +#define _DLM_POINTERS_H + +extern int crdlm_pointers_Bitmap( struct instanceBitmap *instance, GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap, CRClientState *c); +extern int crdlm_pointers_DrawPixels( struct instanceDrawPixels *instance, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ); +extern int crdlm_pointers_Fogfv( struct instanceFogfv *instance, GLenum pname, const GLfloat *params ); +extern int crdlm_pointers_Fogiv( struct instanceFogiv *instance, GLenum pname, const GLint *params ); +extern int crdlm_pointers_LightModelfv( struct instanceLightModelfv *instance, GLenum pname, const GLfloat *params ); +extern int crdlm_pointers_LightModeliv( struct instanceLightModeliv *instance, GLenum pname, const GLint *params ); +extern int crdlm_pointers_Lightfv( struct instanceLightfv *instance, GLenum light, GLenum pname, const GLfloat *params ); +extern int crdlm_pointers_Lightiv( struct instanceLightiv *instance, GLenum light, GLenum pname, const GLint *params ); +extern int crdlm_pointers_Map1d( struct instanceMap1d *instance, GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points ); +extern int crdlm_pointers_Map1f( struct instanceMap1f *instance, GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points ); +extern int crdlm_pointers_Map2d( struct instanceMap2d *instance, GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points ); +extern int crdlm_pointers_Map2f( struct instanceMap2f *instance, GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points ); +extern int crdlm_pointers_Materialfv(struct instanceMaterialfv *instance, GLenum face, GLenum pname, const GLfloat *params); +extern int crdlm_pointers_Materialiv(struct instanceMaterialiv *instance, GLenum face, GLenum pname, const GLint *params); +extern int crdlm_pointers_PixelMapfv( struct instancePixelMapfv *instance, GLenum map, GLsizei mapsize, const GLfloat *values ); +extern int crdlm_pointers_PixelMapuiv( struct instancePixelMapuiv *instance, GLenum map, GLsizei mapsize, const GLuint *values ); +extern int crdlm_pointers_PixelMapusv( struct instancePixelMapusv *instance, GLenum map, GLsizei mapsize, const GLushort *values ); +extern int crdlm_pointers_PointParameterfvARB( struct instancePointParameterfvARB *instance, GLenum pname, const GLfloat *params); +extern int crdlm_pointers_PointParameteriv( struct instancePointParameteriv *instance, GLenum pname, const GLint *params); +extern int crdlm_pointers_TexEnvfv( struct instanceTexEnvfv *instance, GLenum target, GLenum pname, const GLfloat *params ); +extern int crdlm_pointers_TexEnviv( struct instanceTexEnviv *instance, GLenum target, GLenum pname, const GLint *params ); +extern int crdlm_pointers_TexGendv( struct instanceTexGendv *instance, GLenum coord, GLenum pname, const GLdouble *params ); +extern int crdlm_pointers_TexGenfv( struct instanceTexGenfv *instance, GLenum coord, GLenum pname, const GLfloat *params ); +extern int crdlm_pointers_TexGeniv( struct instanceTexGeniv *instance, GLenum coord, GLenum pname, const GLint *params ); +extern int crdlm_pointers_TexImage1D( struct instanceTexImage1D *instance, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ); +extern int crdlm_pointers_CompressedTexImage1DARB(struct instanceCompressedTexImage1DARB *instance, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imagesize, const GLvoid *data); +extern int crdlm_pointers_TexImage2D( struct instanceTexImage2D *instance, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ); +extern int crdlm_pointers_CompressedTexImage2DARB(struct instanceCompressedTexImage2DARB *instance, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imagesize, const GLvoid *data); +extern int crdlm_pointers_TexImage3D( struct instanceTexImage3D *instance, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ); +extern int crdlm_pointers_TexImage3DEXT( struct instanceTexImage3DEXT *instance, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ); +extern int crdlm_pointers_CompressedTexImage3DARB(struct instanceCompressedTexImage3DARB *instance, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imagesize, const GLvoid *data); +extern int crdlm_pointers_TexParameterfv( struct instanceTexParameterfv *instance, GLenum target, GLenum pname, const GLfloat *params ); +extern int crdlm_pointers_TexParameteriv( struct instanceTexParameteriv *instance, GLenum target, GLenum pname, const GLint *params ); +extern int crdlm_pointers_TexSubImage1D( struct instanceTexSubImage1D *instance, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ); +extern int crdlm_pointers_TexSubImage2D( struct instanceTexSubImage2D *instance, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ); +extern int crdlm_pointers_TexSubImage3D( struct instanceTexSubImage3D *instance, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels, CRClientState *c ); +extern int crdlm_pointers_CompressedTexSubImage1DARB(struct instanceCompressedTexSubImage1DARB *instance, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imagesize, const GLvoid *data); +extern int crdlm_pointers_CompressedTexSubImage2DARB(struct instanceCompressedTexSubImage2DARB *instance, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imagesize, const GLvoid *data); +extern int crdlm_pointers_CompressedTexSubImage3DARB(struct instanceCompressedTexSubImage3DARB *instance, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imagesize, const GLvoid *data); +extern int crdlm_pointers_Rectdv(struct instanceRectdv *instance, const GLdouble *v1, const GLdouble *v2); +extern int crdlm_pointers_Rectfv(struct instanceRectfv *instance, const GLfloat *v1, const GLfloat *v2); +extern int crdlm_pointers_Rectiv(struct instanceRectiv *instance, const GLint *v1, const GLint *v2); +extern int crdlm_pointers_Rectsv(struct instanceRectsv *instance, const GLshort *v1, const GLshort *v2); +extern int crdlm_pointers_PrioritizeTextures(struct instancePrioritizeTextures *instance, GLsizei n, const GLuint *textures, const GLclampf *priorities); +extern int crdlm_pointers_CombinerParameterivNV(struct instanceCombinerParameterivNV *instance, GLenum pname, const GLint *params); +extern int crdlm_pointers_CombinerParameterfvNV(struct instanceCombinerParameterfvNV *instance, GLenum pname, const GLfloat *params); +extern int crdlm_pointers_CombinerStageParameterfvNV(struct instanceCombinerStageParameterfvNV *instance, GLenum stage, GLenum pname, const GLfloat *params); +extern int crdlm_pointers_ExecuteProgramNV(struct instanceExecuteProgramNV *instance, GLenum target, GLuint id, const GLfloat *params); +extern int crdlm_pointers_RequestResidentProgramsNV(struct instanceRequestResidentProgramsNV *instance, GLsizei n, const GLuint *ids); +extern int crdlm_pointers_LoadProgramNV(struct instanceLoadProgramNV *instance, GLenum target, GLuint id, GLsizei len, const GLubyte *program); +extern int crdlm_pointers_ProgramNamedParameter4dNV(struct instanceProgramNamedParameter4dNV *instance, GLuint id, GLsizei len, const GLubyte * name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +extern int crdlm_pointers_ProgramNamedParameter4dvNV(struct instanceProgramNamedParameter4dvNV *instance, GLuint id, GLsizei len, const GLubyte * name, const GLdouble * v); +extern int crdlm_pointers_ProgramNamedParameter4fNV(struct instanceProgramNamedParameter4fNV *instance, GLuint id, GLsizei len, const GLubyte * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +extern int crdlm_pointers_ProgramNamedParameter4fvNV(struct instanceProgramNamedParameter4fvNV *instance, GLuint id, GLsizei len, const GLubyte * name, const GLfloat * v); +extern int crdlm_pointers_ProgramStringARB(struct instanceProgramStringARB *instance, GLenum target, GLenum format, GLsizei len, const GLvoid * string); +extern int crdlm_pointers_CallLists(struct instanceCallLists *instance, GLsizei n, GLenum type, const GLvoid *lists ); +extern int crdlm_pointers_VertexAttribs1dvNV(struct instanceVertexAttribs1dvNV *instance, GLuint index, GLsizei n, const GLdouble *v); +extern int crdlm_pointers_VertexAttribs1fvNV(struct instanceVertexAttribs1fvNV *instance, GLuint index, GLsizei n, const GLfloat *v); +extern int crdlm_pointers_VertexAttribs1svNV(struct instanceVertexAttribs1svNV *instance, GLuint index, GLsizei n, const GLshort *v); +extern int crdlm_pointers_VertexAttribs2dvNV(struct instanceVertexAttribs2dvNV *instance, GLuint index, GLsizei n, const GLdouble *v); +extern int crdlm_pointers_VertexAttribs2fvNV(struct instanceVertexAttribs2fvNV *instance, GLuint index, GLsizei n, const GLfloat *v); +extern int crdlm_pointers_VertexAttribs2svNV(struct instanceVertexAttribs2svNV *instance, GLuint index, GLsizei n, const GLshort *v); +extern int crdlm_pointers_VertexAttribs3dvNV(struct instanceVertexAttribs3dvNV *instance, GLuint index, GLsizei n, const GLdouble *v); +extern int crdlm_pointers_VertexAttribs3fvNV(struct instanceVertexAttribs3fvNV *instance, GLuint index, GLsizei n, const GLfloat *v); +extern int crdlm_pointers_VertexAttribs3svNV(struct instanceVertexAttribs3svNV *instance, GLuint index, GLsizei n, const GLshort *v); +extern int crdlm_pointers_VertexAttribs4dvNV(struct instanceVertexAttribs4dvNV *instance, GLuint index, GLsizei n, const GLdouble *v); +extern int crdlm_pointers_VertexAttribs4fvNV(struct instanceVertexAttribs4fvNV *instance, GLuint index, GLsizei n, const GLfloat *v); +extern int crdlm_pointers_VertexAttribs4svNV(struct instanceVertexAttribs4svNV *instance, GLuint index, GLsizei n, const GLshort *v); +extern int crdlm_pointers_VertexAttribs4ubvNV(struct instanceVertexAttribs4ubvNV *instance, GLuint index, GLsizei n, const GLubyte *v); +extern int crdlm_pointers_ZPixCR( struct instanceZPixCR *instance, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum ztype, GLint zparm, GLint length, const GLvoid *pixels, CRClientState *c ); + +#endif diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_special b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_special new file mode 100644 index 00000000..bcbd643e --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_special @@ -0,0 +1,21 @@ +# dlm_arrays.c: these have to be expanded out into +# their components before being stored in a display list +ArrayElement +DrawArrays +DrawElements +DrawRangeElements +MultiDrawArraysEXT +MultiDrawElementsEXT + +# dlm_calllist.c: since the DLM can manage state stored +# inside display lists, we can manage state updates for +# these sorts of elements. +#CallList +#CallLists + +# Calls to be ignored. +#VBoxConCreate +#VBoxCreateContext +#VBoxPackSetInjectThread +#VBoxPresentComposition +#VBoxWindowCreate diff --git a/src/VBox/HostServices/SharedOpenGL/dlm/dlm_state.c b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_state.c new file mode 100644 index 00000000..341d62e6 --- /dev/null +++ b/src/VBox/HostServices/SharedOpenGL/dlm/dlm_state.c @@ -0,0 +1,280 @@ +/* $Id: dlm_state.c $ */ +/** @file + * Implementation of saving and restoring Display Lists. + */ + +/* + * Copyright (C) 2015-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "cr_mem.h" +#include "cr_dlm.h" +#include "dlm.h" +#include "dlm_generated.h" + +#include "VBox/vmm/ssm.h" +#include <iprt/errcore.h> + + +typedef struct { + + PSSMHANDLE pSSM; + uint32_t err; + +} CRDLMSaveListsCbArg; + +static void crDLMSaveListsCb(unsigned long key, void *pData1, void *pData2) +{ + DLMListInfo *pListInfo = (DLMListInfo*)pData1; + CRDLMSaveListsCbArg *pArg = (CRDLMSaveListsCbArg *)pData2; + PSSMHANDLE pSSM = pArg->pSSM; + DLMInstanceList *pInstance = pListInfo->first; + uint32_t cInstanceCheck = 0; + int32_t rc; + + crDebug("Saving Display Lists: found ID=%u, numInstances=%d.", key, pListInfo->numInstances); + + /* Store Display List length. */ + rc = SSMR3PutU32(pSSM, pListInfo->numInstances); + if (RT_SUCCESS(rc)) + { + /* Store Display List (guest) ID. */ + rc = SSMR3PutU32(pSSM, (uint32_t)key); + if (RT_SUCCESS(rc)) + { + /* Store each Display List item one by one. */ + while (pInstance) + { + /* Let's count each list item and compare total number with pListInfo->numInstances. + * This is simple consistency check. */ + cInstanceCheck++; + + /* Store instance data size. */ + rc = SSMR3PutU32(pSSM, (uint32_t)pInstance->cbInstance); + if (RT_SUCCESS(rc)) + { + rc = SSMR3PutMem(pSSM, pInstance, pInstance->cbInstance); + if (RT_SUCCESS(rc)) + { + /* We just stored all we need. Let's move on to the next list element. */ + pInstance = pInstance->next; + continue; + } + } + + crError("Saving Display Lists: can't store data."); + + pArg->err = 1; + return; + } + + if (cInstanceCheck == pListInfo->numInstances) + return; + + crError("Saving Display Lists: list currupted."); + } + } + + pArg->err = 1; +} + +int32_t DLM_APIENTRY crDLMSaveState(CRDLM *dlm, PSSMHANDLE pSSM) +{ + uint32_t ui32; + int32_t rc; + + CRDLMSaveListsCbArg arg; + + arg.pSSM = pSSM; + arg.err = 0; + + /* Save number of Display Lists assigned to current DLM context. */ + ui32 = (uint32_t)crHashtableNumElements(dlm->displayLists); + rc = SSMR3PutU32(pSSM, ui32); AssertRCReturn(rc, rc); + + crHashtableWalk(dlm->displayLists, crDLMSaveListsCb, (void *)&arg); + + return arg.err == 0; +} + +static VBoxDLMExecuteFn crDLMGetExecuteRoutine(VBoxDLOpCode opcode) +{ + if (opcode < VBOX_DL_OPCODE_MAX) + return g_VBoxDLMExecuteFns[opcode]; + + crError("Restoring Display Lists: Invalid opcode %u.", opcode); + + return NULL; +} + +static bool +crDLMLoadListInstance(PSSMHANDLE pSSM, DLMListInfo *pListInfo, SPUDispatchTable *dispatchTable) +{ + uint32_t cbInstance = 0; + DLMInstanceList *pInstance; + int32_t rc; + + /* Get Display List item size. */ + rc = SSMR3GetU32(pSSM, &cbInstance); + if (RT_SUCCESS(rc)) + { + /* Allocate memory for the item, initialize it and put into the list. */ + pInstance = crCalloc(cbInstance); + if (pInstance) + { + crMemset(pInstance, 0, cbInstance); + + rc = SSMR3GetMem(pSSM, pInstance, cbInstance); AssertRCReturn(rc, rc); + if (RT_SUCCESS(rc)) + { + pInstance->execute = crDLMGetExecuteRoutine(pInstance->iVBoxOpCode); + if (pInstance->execute) + { + pInstance->execute(pInstance, dispatchTable); + + pInstance->next = NULL; + pInstance->stateNext = NULL; + pInstance->cbInstance = cbInstance; + + pListInfo->numInstances++; + + if (!pListInfo->first) + pListInfo->first = pInstance; + + if (pListInfo->last) + pListInfo->last->next = pInstance; + + pListInfo->last = pInstance; + + return true; + } + else + crError("Restoring Display Lists: unknown list item (opcode=%u).", pInstance->iVBoxOpCode); + } + else + crError("Restoring Display Lists: can't read list element size."); + } + else + crError("Restoring Display Lists: not enough memory, aborting."); + } + else + crError("Restoring Display Lists: saved state file might be corrupted."); + + return false; +} + +static bool +crDLMLoadList(CRDLM *dlm, PSSMHANDLE pSSM, SPUDispatchTable *dispatchTable) +{ + uint32_t cElements = 0; + uint32_t idList = 0; + uint32_t i; + int32_t rc; + + /* Restore Display List length. */ + rc = SSMR3GetU32(pSSM, &cElements); + if (RT_SUCCESS(rc)) + { + /* Restore Display List ID. */ + rc = SSMR3GetU32(pSSM, &idList); + if (RT_SUCCESS(rc)) + { + /* Initialize new list data and start recording it. */ + DLMListInfo *pListInfo; + + pListInfo = (DLMListInfo *)crCalloc(sizeof(DLMListInfo)); + if (pListInfo) + { + GLuint hwid; + + crMemset(pListInfo, 0, sizeof(DLMListInfo)); + + hwid = dispatchTable->GenLists(1); + if (hwid > 0) + { + bool fSuccess = true; + CRDLMContextState *pDLMContextState; + + pListInfo->numInstances = 0; + pListInfo->stateFirst = pListInfo->stateLast = NULL; + pListInfo->hwid = hwid; + + dispatchTable->NewList(hwid, GL_COMPILE); + + /* Fake list state in order to prevent expando SPU from double caching. */ + pDLMContextState = crDLMGetCurrentState(); + pDLMContextState->currentListMode = GL_FALSE; + + crDebug("Restoring Display Lists:\t%u elements to restore.", cElements); + + /* Iterate over list instances. */ + for (i = 0; i < cElements; i++) + { + fSuccess = crDLMLoadListInstance(pSSM, pListInfo, dispatchTable); + if (!fSuccess) + break; + } + + dispatchTable->EndList(); + + if (fSuccess) + { + /* Add list to cache. */ + crHashtableReplace(dlm->displayLists, idList, pListInfo, NULL); + return true; + } + else + crError("Restoring Display Lists: some elements could not be restored."); + } + else + crError("Restoring Display Lists: can't allocate hwid for list %u.", idList); + + crFree(pListInfo); + } + else + crError("Restoring Display Lists: can't allocate memory."); + } + else + crError("Restoring Display Lists: can't get list ID."); + } + else + crError("Restoring Display Lists: can't get number of elements in list."); + + return false; +} + + +bool DLM_APIENTRY +crDLMLoadState(CRDLM *dlm, PSSMHANDLE pSSM, SPUDispatchTable *dispatchTable) +{ + uint32_t cLists = 0; + uint32_t i; + int32_t rc; + bool fSuccess = true; + + /* Get number of Display Lists assigned to current DLM context. */ + rc = SSMR3GetU32(pSSM, &cLists); + if (RT_SUCCESS(rc)) + { + crDebug("Restoring Display Lists: %u lists to restore.", cLists); + + for (i = 0; i < cLists; i++) + { + fSuccess = crDLMLoadList(dlm, pSSM, dispatchTable); + if (!fSuccess) + break; + } + } + else + crError("Restoring Display Lists: can't get number of lists."); + + return fSuccess; +} |