/* This file contains the low-level support code for OS surfaces. Since FXBlt may operate on any of these some functions must be provided by the client. It is crucial that every client creating surfaces for use by Squeak registers the surfaces using the functions provided here. Other concrete primitives (such as creation or destroy) of surfaces can be handled by additional support code, querying the surface handle from ioFindSurface but the functions provided below are critical for any BitBlt operations. */ #include #include #include #include #include /* Default EXPORT macro that does nothing (see comment in sq.h): */ #define EXPORT(returnType) returnType #include "sqVirtualMachine.h" #include "sqConfig.h" #include "sqPlatformSpecific.h" #include "SurfacePlugin.h" /* internal plugin support */ #ifdef SQUEAK_BUILTIN_PLUGIN #undef EXPORT #define EXPORT(returnType) static returnType #endif typedef struct SqueakSurface { int handle; /* client supplied handle */ sqSurfaceDispatch *dispatch; } SqueakSurface; static SqueakSurface *surfaceArray = NULL; static int numSurfaces = 0; static int maxSurfaces = 0; #ifdef SQUEAK_BUILTIN_PLUGIN static const char *moduleName = "SurfacePlugin "__DATE__" (i)"; #else static const char *moduleName = "SurfacePlugin "__DATE__" (e)"; #endif static VirtualMachine *interpreterProxy; #define FAIL { interpreterProxy->primitiveFail(); return 0; } #pragma export on /* module initialization/shutdown */ EXPORT(int) setInterpreter(struct VirtualMachine *interpreterProxy); EXPORT(const char*) getModuleName(void); EXPORT(int) initialiseModule(void); EXPORT(int) shutdownModule(void); /* critical FXBlt entry points */ EXPORT(int) ioGetSurfaceFormat (int surfaceID, int* width, int* height, int* depth, int* isMSB); EXPORT(int) ioLockSurface (int surfaceID, int *pitch, int x, int y, int w, int h); EXPORT(int) ioUnlockSurface(int surfaceID, int x, int y, int w, int h); /* interpreter entry point */ EXPORT(int) ioShowSurface(int surfaceID, int x, int y, int w, int h); /* client entry points */ EXPORT(int) ioRegisterSurface(int surfaceHandle, sqSurfaceDispatch *fn, int *surfaceID); EXPORT(int) ioUnregisterSurface(int surfaceID); EXPORT(int) ioFindSurface(int surfaceID, sqSurfaceDispatch *fn, int *surfaceHandle); #pragma export off /* ioGetSurfaceFormat: Return information describing the given surface. Return true if successful, false otherwise. */ EXPORT(int) ioGetSurfaceFormat (int surfaceID, int* width, int* height, int* depth, int* isMSB) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) FAIL; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) FAIL; if(!surface->dispatch->getSurfaceFormat) FAIL; return surface->dispatch->getSurfaceFormat(surface->handle, width, height, depth, isMSB); } /* ioLockSurface: Lock the bits of the surface. Return a pointer to the actual surface bits, or NULL on failure. */ EXPORT(int) ioLockSurface (int surfaceID, int *pitch, int x, int y, int w, int h) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) FAIL; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) FAIL; if(!surface->dispatch->lockSurface) FAIL; return surface->dispatch->lockSurface(surface->handle, pitch, x, y, w, h); } /* ioUnlockSurface: Unlock the bits of the surface. The return value is ignored. */ EXPORT(int) ioUnlockSurface(int surfaceID, int x, int y, int w, int h) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) FAIL; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) FAIL; if(!surface->dispatch->unlockSurface) FAIL; return surface->dispatch->unlockSurface(surface->handle, x, y, w, h); } /* ioShowSurface: Transfer the bits of a surface to the screen. */ EXPORT(int) ioShowSurface(int surfaceID, int x, int y, int w, int h) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) FAIL; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) FAIL; if(!surface->dispatch->showSurface) FAIL; return surface->dispatch->showSurface(surface->handle, x, y, w, h); } /* ioRegisterSurface: Register a new surface with the given handle and the set of surface functions. The new ID is returned in surfaceID. Returns true if successful, false otherwise. */ EXPORT(int) ioRegisterSurface(int surfaceHandle, sqSurfaceDispatch *fn, int *surfaceID) { int index; if(!fn) return 0; if(fn->majorVersion != 1 && fn->minorVersion != 0) return 0; if(numSurfaces == maxSurfaces) { maxSurfaces = maxSurfaces * 2 + 10; surfaceArray = realloc(surfaceArray, sizeof(SqueakSurface) * maxSurfaces); for(index = numSurfaces; index < maxSurfaces; index++){ surfaceArray[index].handle = 0; surfaceArray[index].dispatch = NULL; } index = numSurfaces; } else { for(index = 0; index < maxSurfaces; index++) if(surfaceArray[index].dispatch == NULL) break; } if(index >= maxSurfaces) return 0; /* should not happen */ surfaceArray[index].handle = surfaceHandle; surfaceArray[index].dispatch = fn; *surfaceID = index; numSurfaces++; return 1; } /* ioUnregisterSurface: Unregister the surface with the given handle. Returns true if successful, false otherwise. */ EXPORT(int) ioUnregisterSurface(int surfaceID) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) return 0; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) return 0; surface->handle = 0; surface->dispatch = NULL; numSurfaces--; return 1; } /* ioFindSurface: Find the surface with the given ID, and, optionally, the given set of surface functions. The registered handle is returned in surfaceHandle. Return true if successful (e.g., the surface has been found), false otherwise. */ EXPORT(int) ioFindSurface(int surfaceID, sqSurfaceDispatch *fn, int *surfaceHandle) { SqueakSurface *surface; if(surfaceID < 0 || surfaceID >= maxSurfaces) return 0; surface = surfaceArray + surfaceID; if(surface->dispatch == NULL) return 0; if(fn && fn != surface->dispatch) return 0; *surfaceHandle = surface->handle; return 1; } EXPORT(int) setInterpreter(struct VirtualMachine* anInterpreter) { int ok; interpreterProxy = anInterpreter; ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; if (ok == 0) { return 0; } ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; return ok; } EXPORT(const char*) getModuleName(void) { return moduleName; } EXPORT(int) initialiseModule() { surfaceArray = NULL; numSurfaces = 0; maxSurfaces = 0; return 1; } EXPORT(int) shutdownModule() { /* This module can only be shut down if no surfaces are registered */ if(numSurfaces != 0) return 0; free(surfaceArray); return 1; } #ifdef SQUEAK_BUILTIN_PLUGIN void* SurfacePlugin_exports[][3] = { {"SurfacePlugin", "setInterpreter", (void*)setInterpreter}, {"SurfacePlugin", "getModuleName", (void*)getModuleName}, {"SurfacePlugin", "initialiseModule", (void*)initialiseModule}, {"SurfacePlugin", "shutdownModule", (void*)shutdownModule}, {"SurfacePlugin", "ioGetSurfaceFormat", (void*)ioGetSurfaceFormat}, {"SurfacePlugin", "ioLockSurface", (void*)ioLockSurface}, {"SurfacePlugin", "ioUnlockSurface", (void*)ioUnlockSurface}, {"SurfacePlugin", "ioShowSurface", (void*)ioShowSurface}, {"SurfacePlugin", "ioRegisterSurface", (void*)ioRegisterSurface}, {"SurfacePlugin", "ioUnregisterSurface", (void*)ioUnregisterSurface}, {"SurfacePlugin", "ioFindSurface", (void*)ioFindSurface}, {NULL, NULL, NULL} }; #endif /* ifdef SQ_BUILTIN_PLUGIN */