/*
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 <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* 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 */
|