#include "sqFFI.h" #include "sq.h" #include "sqVirtualMachine.h" extern struct VirtualMachine* interpreterProxy; /* Need separate cases for GNU C and MSVC. */ #ifdef DEBUG #warning "DEBUG printing enabled" #define DPRINTF(x) warnPrintf x #elif defined(_DEBUG) #pragma message ( "DEBUG printing enabled" ) #define DPRINTF(x) warnPrintf x #else #define DPRINTF(x) #endif #ifndef NULL #define NULL 0 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /* Don't want to mess with EXPORT status of functions in SurfacePlugin.c, we use function-pointers here. */ static fn_ioRegisterSurface registerSurface = NULL; static fn_ioUnregisterSurface unregisterSurface = NULL; static fn_ioFindSurface findSurface = NULL; void initSurfacePluginFunctionPointers() { registerSurface = (fn_ioRegisterSurface) interpreterProxy->ioLoadFunctionFrom("ioRegisterSurface","SurfacePlugin"); unregisterSurface = (fn_ioUnregisterSurface) interpreterProxy->ioLoadFunctionFrom("ioUnregisterSurface","SurfacePlugin"); findSurface = (fn_ioFindSurface) interpreterProxy->ioLoadFunctionFrom("ioFindSurface","SurfacePlugin"); } /* This is the structure that represents a "manual surface". These are created/destroyed by new primitives in this plugin. During it's life-time, it may be touched directly from Squeak code to set/clear "ptr", and also treated as a generic surface via BitBlt's use of the SurfacePlugin. */ typedef struct { int width; int height; int rowPitch; int depth; int isMSB; void* ptr; int isLocked; } ManualSurface; /* Create the dispatch-table that SurfacePlugin will use to interact with instances of "struct ManualSurface" */ static int manualSurfaceGetFormat(ManualSurface* surface, int* width, int* height, int* depth, int* isMSB); static void* manualSurfaceLock(ManualSurface* surface, int *pitch, int x, int y, int w, int h); static int manualSurfaceUnlock(ManualSurface* surface, int x, int y, int w, int h); static int manualSurfaceShow(ManualSurface* surface, int x, int y, int w, int h); static sqSurfaceDispatch manualSurfaceDispatch = { 1, 0, (fn_getSurfaceFormat) manualSurfaceGetFormat, (fn_lockSurface) manualSurfaceLock, (fn_unlockSurface) manualSurfaceUnlock, (fn_showSurface) manualSurfaceShow }; /* sqSurfaceDispatch functions *****************************************************************************/ int manualSurfaceGetFormat(ManualSurface* surface, int* width, int* height, int* depth, int* isMSB) { *width = surface->width; *height = surface->height; *depth = surface->depth; *isMSB = surface->isMSB; DPRINTF(("Getting Surface Format: %lx %d %d %d %d\n", ((int) surface), *width, *height, *depth, *isMSB)); return 1; } void* manualSurfaceLock(ManualSurface* surface, int *pitch, int x, int y, int w, int h) { /* Ideally, would be atomic. But it doens't matter for the forseeable future, since it is only called via BitBlt primitives. */ int wasLocked = surface->isLocked; surface->isLocked = 1; /* Can't lock if it was already locked. */ if (wasLocked) return NULL; /* If there is no pointer, the lock-attempt fails. */ if (!surface->ptr) { surface->isLocked = 0; return NULL; } /* Success! Return the pointer. */ *pitch = surface->rowPitch; DPRINTF(("Locked Surface: %lx Input Rect: %d %d %d %d Row Pitch: %d\n", ((int) surface), x, y, w, h, *pitch)); return surface->ptr; } int manualSurfaceUnlock(ManualSurface* surface, int x, int y, int w, int h) { surface->isLocked = 0; DPRINTF(("Unlocked Surface: %lx Rect: %d %d %d %d\n", ((int) surface), x, y, w, h)); return 1; } int manualSurfaceShow(ManualSurface* surface, int x, int y, int w, int h) { /* Unsupported */ return 0; } /* primitive interface functions (i.e. called from Squeak) *********************************************/ /* Answer non-negative surfaceID if successful, and -1 for failure. */ int createManualSurface(int width, int height, int rowPitch, int depth, int isMSB) { ManualSurface* newSurface; int surfaceID; int result; if (width < 0) return -1; if (height < 0) return -1; if (rowPitch < (width*depth)/8) return -1; if (depth < 1 || depth > 32) return -1; if (!registerSurface) return -1; /* failure... couldn't init function-pointer */ newSurface = (ManualSurface*)malloc(sizeof(ManualSurface)); if (!newSurface) return -1; newSurface->width = width; newSurface->height = height; newSurface->rowPitch = rowPitch; newSurface->depth = depth; newSurface->isMSB = isMSB; newSurface->ptr = NULL; newSurface->isLocked = FALSE; result = registerSurface((int)newSurface, &manualSurfaceDispatch, &surfaceID); if (!result) { /* Failed to register surface. */ free(newSurface); return -1; } else { return surfaceID; } } int destroyManualSurface(int surfaceID) { if (!unregisterSurface) return 0; /* failure... couldn't init function-pointer */ else return unregisterSurface(surfaceID); } int setManualSurfacePointer(int surfaceID, void* ptr) { int surfaceHandle; ManualSurface *surface; int result; if (!findSurface) return FALSE; /* failure... couldn't init function-pointer */ result = findSurface(surfaceID, NULL, &surfaceHandle); if (!result) return FALSE; /* failed to find surface */ surface = (ManualSurface*)surfaceHandle; if (surface->isLocked) return FALSE; /* can't set pointer while surface is locked */ surface->ptr = ptr; DPRINTF(("Set Surface: %lx Pointer: %lx\n", surfaceID, ((int)ptr) )); return TRUE; }