/* * $Id$ * * $Date$ * $Revision$ * * (C) 1999 by Hyperion * All rights reserved * * This file is part of the MiniGL library project * See the file Licence.txt for more details * */ #include "sysinc.h" #include #include #include #ifdef USE_68K_SWITCHER #warning "Using 68k switcher code" #include "switchercode.h" // We use this function, as libppcamiga.a's CreateTask is broken. extern struct Task * Create68kTask( char *name, ULONG pri, APTR initPC, ULONG stackSize ); #endif static char rcsid[] UNUSED = "$Id$"; extern void GLMatrixInit(GLcontext context); GLboolean MGLInitContext(GLcontext context); #ifndef __PPC__ extern struct IntuitionBase *IntuitionBase; extern struct ExecBase *SysBase; extern struct GfxBase *GfxBase; extern struct DosLibrary *DOSBase; #endif GLcontext mini_CurrentContext; #ifdef __PPC__ extern struct Library *Warp3DPPCBase; #else extern struct Library *Warp3DBase; #endif extern struct Library *CyberGfxBase; extern void tex_FreeTextures(GLcontext context); extern void TMA_Start(LockTimeHandle *handle); #ifndef NLOGGING int MGLDebugLevel; #endif // Default values for new context static int newVertexBufferSize = 40; // Default: 40 entries in vertex buffer static int newTextureBufferSize = 2048; // Default: 2048 texture objects static int newNumberOfBuffers = 2; // Default: Double buffering static int newPixelDepth = 15; // Default: 15 bits per pixel static GLboolean newWindowMode = GL_FALSE; // Default: Use fullscreen instead of window static GLboolean clw = GL_FALSE; // Default: Keep workbench open static GLboolean newNoMipMapping = GL_TRUE; // Default: No mipmapping static GLboolean newNoFallbackAlpha = GL_FALSE; // Default: Fall back to supported blend mode static struct TagItem tags[7]; static UWORD *MousePointer = 0; static GLboolean sys_MaybeOpenVidLibs(void) { #ifdef __PPC__ if (!Warp3DPPCBase) { Warp3DPPCBase = OpenLibrary("Warp3DPPC.library", 2L); if (!Warp3DPPCBase) { printf("Error opening Warp3D library\n"); return GL_FALSE; } } #else if (!Warp3DBase) { Warp3DBase = OpenLibrary("Warp3D.library", 2L); if (!Warp3DBase) { printf("Error opening Warp3D library\n"); return GL_FALSE; } } #endif if (!CyberGfxBase) { CyberGfxBase = OpenLibrary("cybergraphics.library", 0L); if (!CyberGfxBase) { printf("Error opening cybergraphics.library\n"); return GL_FALSE; } } return GL_TRUE; } static void vid_Pointer(struct Window *window) { if (!MousePointer) { #ifdef __PPC__ MousePointer = AllocVecPPC(12, MEMF_CLEAR|MEMF_CHIP,0); #else MousePointer = AllocVec(12, MEMF_CLEAR|MEMF_CHIP); #endif } if (window) SetPointer(window, MousePointer, 1, 16, 0, 0); } static void vid_DeletePointer(struct Window *window) { if (window) ClearPointer(window); #ifdef __PPC__ FreeVecPPC(MousePointer); #else FreeVec(MousePointer); #endif MousePointer = 0; } void GLScissor(GLcontext context, GLint x, GLint y, GLsizei width, GLsizei height) { //LOG(1, glScissor, "%d %d %d %d",x,y,width,height); context->scissor.left = x; context->scissor.top = context->w3dWindow->Height-y-height; context->scissor.width = width; context->scissor.height = height; } static void vid_CloseDisplay(GLcontext context) { int i; if (context->w3dContext) { W3D_FreeZBuffer(context->w3dContext); tex_FreeTextures(context); W3D_DestroyContext(context->w3dContext); context->w3dContext = 0; } #ifdef __PPC__ if (Warp3DPPCBase) CloseLibrary(Warp3DPPCBase); Warp3DPPCBase = NULL; #else if (Warp3DBase) CloseLibrary(Warp3DBase); Warp3DBase = NULL; #endif Delay(25L); if (context->Buffers[0]) { context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[0])); } for (i=0; iNumBuffers; i++) { if (context->Buffers[i]) FreeScreenBuffer(context->w3dScreen, context->Buffers[i]); context->Buffers[i] = NULL; } vid_DeletePointer(context->w3dWindow); if (context->w3dWindow) CloseWindow(context->w3dWindow); if (context->w3dScreen) CloseScreen(context->w3dScreen); if (clw == GL_TRUE) OpenWorkBench(); } static GLboolean vid_ReopenDisplay(GLcontext context, int w, int h) { ULONG ModeID, IDCMP; int i; struct TagItem BestModeTags[] = { {W3D_BMI_WIDTH, 0}, {W3D_BMI_HEIGHT, 0}, {W3D_BMI_DEPTH, 0}, {TAG_DONE, 0} }; #ifndef NCGXDEBUG ULONG flag; if (GL_FALSE == sys_MaybeOpenVidLibs()) { return GL_FALSE; } #endif if (context->Buffers[0]) { context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[0])); } for (i=0; iNumBuffers; i++) { if (context->Buffers[i]) FreeScreenBuffer(context->w3dScreen, context->Buffers[i]); context->Buffers[i] = NULL; } IDCMP = context->w3dWindow->IDCMPFlags; if (context->w3dWindow) CloseWindow(context->w3dWindow); context->w3dWindow = NULL; if (context->w3dScreen) CloseScreen(context->w3dScreen); context->w3dScreen = NULL; BestModeTags[0].ti_Data = (ULONG)w; BestModeTags[1].ti_Data = (ULONG)h; BestModeTags[2].ti_Data = (ULONG)newPixelDepth; ModeID = W3D_BestModeID(BestModeTags); if (ModeID == INVALID_ID) return GL_FALSE; context->w3dScreen = OpenScreenTags(NULL, SA_Height, h, SA_Width, w, SA_Depth, 8L, SA_DisplayID, ModeID, SA_ShowTitle, FALSE, SA_Draggable, FALSE, TAG_DONE); if (!context->w3dScreen) { printf("Failed to re-open screen\n"); return GL_FALSE; } context->w3dWindow = OpenWindowTags(NULL, WA_CustomScreen, (ULONG)context->w3dScreen, WA_Width, (ULONG)context->w3dScreen->Width, WA_Height, (ULONG)context->w3dScreen->Height, WA_Left, 0, WA_Top, 0, WA_Title, NULL, WA_Flags, WFLG_ACTIVATE|WFLG_BORDERLESS|WFLG_BACKDROP| WFLG_REPORTMOUSE|WFLG_RMBTRAP, WA_IDCMP, IDCMP, TAG_DONE); if (!context->w3dWindow) { printf("Failed to re-open window\n"); goto Duh; } context->Buffers[0] = AllocScreenBuffer(context->w3dScreen, NULL, SB_SCREEN_BITMAP); if (!context->Buffers[0]) { printf("Failed to allocate screen buffer\n"); goto Duh; } #ifndef NCGXDEBUG flag = GetCyberMapAttr(context->Buffers[0]->sb_BitMap, CYBRMATTR_ISCYBERGFX); if (!flag) printf("Warning: No CyberGraphics bitmap in buffer 0\n"); else printf("Info: Buffer 0 is a cybergraphics bitmap\n"); #endif for (i=1; iBuffers[i] = AllocScreenBuffer(context->w3dScreen, NULL, 0); if (!context->Buffers[i]) goto Duh; #ifndef NCGXDEBUG flag = GetCyberMapAttr(context->Buffers[0]->sb_BitMap, CYBRMATTR_ISCYBERGFX); if (!flag) printf("Warning: No CyberGraphics bitmap in buffer %d\n", i); else printf("Info: Buffer %d is a cybergraphics bitmap\n", i); #endif } context->BufNr = 1; // The drawing buffer SetRGB32(&(context->w3dScreen->ViewPort), 0, 0x7fffffff,0x7fffffff,0x7fffffff); for (i=0; iNumBuffers; i++) { context->Buffers[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[i])); EraseRect(context->w3dWindow->RPort, context->w3dWindow->BorderLeft, context->w3dWindow->BorderTop, context->w3dWindow->Width-context->w3dWindow->BorderLeft-context->w3dWindow->BorderRight-1, context->w3dWindow->Height-context->w3dWindow->BorderTop-context->w3dWindow->BorderBottom-1); } context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[0])); GLScissor(context, 0, 0, w, h); W3D_SetDrawRegion(context->w3dContext, context->Buffers[1]->sb_BitMap, 0, &(context->scissor)); W3D_FreeZBuffer(context->w3dContext); W3D_AllocZBuffer(context->w3dContext); vid_Pointer(context->w3dWindow); return GL_TRUE; Duh: printf("An error occured - closing down\n"); vid_CloseDisplay(context); return GL_FALSE; } static GLboolean vid_OpenDisplay(GLcontext context, int pw, int ph, ULONG id) { ULONG ModeID; ULONG CError; int i; ULONG result; #ifndef NCGXDEBUG ULONG flag; #endif int w = 0, h = 0; struct TagItem BestModeTags[] = { {W3D_BMI_WIDTH, 0}, {W3D_BMI_HEIGHT, 0}, {W3D_BMI_DEPTH, 0}, {TAG_DONE, 0} }; if (GL_FALSE == sys_MaybeOpenVidLibs()) { return GL_FALSE; } if (id != MGL_SM_BESTMODE && id != MGL_SM_WINDOWMODE) { ModeID = id; } else { w = pw; h = ph; BestModeTags[0].ti_Data = (ULONG)w; BestModeTags[1].ti_Data = (ULONG)h; BestModeTags[2].ti_Data = (ULONG)newPixelDepth; ModeID = W3D_BestModeID(BestModeTags); } if (clw == GL_TRUE) CloseWorkBench(); if (ModeID == INVALID_ID) return GL_FALSE; context->w3dScreen = OpenScreenTags(NULL, SA_Depth, 8L, SA_DisplayID, ModeID, SA_ShowTitle, FALSE, SA_Draggable, FALSE, TAG_DONE); if (context->w3dScreen && id != MGL_SM_BESTMODE) { w = context->w3dScreen->Width; h = context->w3dScreen->Height; } if (!context->w3dScreen) return GL_FALSE; // We don't include IDCMP flags. The user can change this with // a call to ModifyIDCMP. context->w3dWindow = OpenWindowTags(NULL, WA_CustomScreen, (ULONG)context->w3dScreen, WA_Width, (ULONG)context->w3dScreen->Width, WA_Height, (ULONG)context->w3dScreen->Height, WA_Left, 0, WA_Top, 0, WA_Title, NULL, WA_Flags, WFLG_ACTIVATE|WFLG_BORDERLESS|WFLG_BACKDROP| WFLG_REPORTMOUSE|WFLG_RMBTRAP, TAG_DONE); if (!context->w3dWindow) goto Duh; context->Buffers[0] = AllocScreenBuffer(context->w3dScreen, NULL, SB_SCREEN_BITMAP); if (!context->Buffers[0]) { printf("Error: Can't create screen buffer 0\n"); goto Duh; } #ifndef NCGXDEBUG flag = GetCyberMapAttr(context->Buffers[0]->sb_BitMap, CYBRMATTR_ISCYBERGFX); if (!flag) printf("Warning: No CyberGraphics bitmap in buffer 0\n"); else printf("Info: Buffer 0 is a cybergraphics bitmap\n"); #endif for (i=1; iBuffers[i] = AllocScreenBuffer(context->w3dScreen, NULL, 0); if (!context->Buffers[i]) { printf("Error: Can't create screen buffer %d\n", i); goto Duh; } #ifndef NCGXDEBUG flag = GetCyberMapAttr(context->Buffers[0]->sb_BitMap, CYBRMATTR_ISCYBERGFX); if (!flag) printf("Warning: No CyberGraphics bitmap in buffer %d\n", i); else printf("Info: Buffer 0 is a cybergraphics bitmap\n"); #endif } context->BufNr = 1; // The drawing buffer context->NumBuffers = newNumberOfBuffers; // So we know the limit context->DoSync = GL_TRUE; // Enable sync'ing tags[0].ti_Tag = W3D_CC_MODEID; tags[0].ti_Data = ModeID; tags[1].ti_Tag = W3D_CC_BITMAP; tags[1].ti_Data = (ULONG)(context->Buffers[1]->sb_BitMap); tags[2].ti_Tag = W3D_CC_DRIVERTYPE; tags[2].ti_Data = W3D_DRIVER_BEST; tags[3].ti_Tag = W3D_CC_FAST; tags[3].ti_Data = FALSE; tags[4].ti_Tag = W3D_CC_YOFFSET; tags[4].ti_Data = 0; tags[5].ti_Tag = W3D_CC_GLOBALTEXENV; tags[5].ti_Data = TRUE; tags[6].ti_Tag = TAG_DONE; context->w3dContext = W3D_CreateContext(&CError, tags); if (!context->w3dContext || CError != W3D_SUCCESS) { switch(CError) { case W3D_ILLEGALINPUT: printf("Illegal input to CreateContext function\n"); break; case W3D_NOMEMORY: printf("Out of memory\n"); break; case W3D_NODRIVER: printf("No suitable driver found\n"); break; case W3D_UNSUPPORTEDFMT: printf("Supplied bitmap cannot be handled by Warp3D\n"); break; case W3D_ILLEGALBITMAP: printf("Supplied bitmap not properly initialized\n"); break; default: printf("An error has occured... gosh\n"); } goto Duh; } /* ** Set up a few initial states ** We always enable scissoring and dithering, since it looks better ** on 16 bit displays. ** We also set shading to smooth (Gouraud). */ W3D_SetState(context->w3dContext, W3D_DITHERING, W3D_ENABLE); W3D_SetState(context->w3dContext, W3D_SCISSOR, W3D_ENABLE); W3D_SetState(context->w3dContext, W3D_GOURAUD, W3D_ENABLE); W3D_SetState(context->w3dContext, W3D_PERSPECTIVE, W3D_ENABLE); SetRGB32(&(context->w3dScreen->ViewPort), 0, 0x7fffffff,0x7fffffff,0x7fffffff); /* ** Allocate the ZBuffer. */ result = W3D_AllocZBuffer(context->w3dContext); switch(result) { case W3D_NOGFXMEM: printf("No ZBuffer: Memory shortage\n"); break; case W3D_NOZBUFFER: printf("No ZBuffer: Operation not supported\n"); break; case W3D_NOTVISIBLE: printf("No ZBuffer: Screen is not visible\n"); break; } W3D_SetState(context->w3dContext, W3D_ZBUFFER, W3D_DISABLE); W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE); W3D_SetZCompareMode(context->w3dContext, W3D_Z_LESS); for (i=0; iNumBuffers; i++) { context->Buffers[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[i])); EraseRect(context->w3dWindow->RPort, context->w3dWindow->BorderLeft, context->w3dWindow->BorderTop, context->w3dWindow->Width-context->w3dWindow->BorderLeft-context->w3dWindow->BorderRight-1, context->w3dWindow->Height-context->w3dWindow->BorderTop-context->w3dWindow->BorderBottom-1); } context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[0])); GLScissor(context, 0,0, w,h); context->w3dLocked = GL_FALSE; /* ** Select a texture format that needs no conversion */ //FIXME:Really do it. This is lame context->w3dFormat = W3D_A1R5G5B5; context->w3dAlphaFormat = W3D_A4R4G4B4; context->w3dBytesPerTexel = 2; vid_Pointer(context->w3dWindow); return GL_TRUE; Duh: for (i=0; iBuffers[i]) { FreeScreenBuffer(context->w3dScreen, context->Buffers[i]); context->Buffers[i] = NULL; } } if (context->w3dWindow) { CloseWindow(context->w3dWindow); context->w3dWindow = NULL; } if (context->w3dScreen) { CloseScreen(context->w3dScreen); context->w3dScreen = NULL; } return GL_FALSE; } static void vid_CloseWindow(GLcontext context) { if (context->w3dContext) { W3D_FreeZBuffer(context->w3dContext); tex_FreeTextures(context); W3D_DestroyContext(context->w3dContext); context->w3dContext = 0; } #ifdef __PPC__ if (Warp3DPPCBase) CloseLibrary(Warp3DPPCBase); Warp3DPPCBase = NULL; #else if (Warp3DBase) CloseLibrary(Warp3DBase); Warp3DBase = NULL; #endif if (context->w3dWindow) CloseWindow(context->w3dWindow); if (context->w3dScreen) CloseScreen(context->w3dScreen); if (context->w3dBitMap) FreeBitMap(context->w3dBitMap); if (context->w3dRastPort) free(context->w3dRastPort); } static GLboolean vid_OpenWindow(GLcontext context, int w, int h) { ULONG CError; ULONG result; if (GL_FALSE == sys_MaybeOpenVidLibs()) { return GL_FALSE; } context->w3dScreen = LockPubScreen(NULL); if (!context->w3dScreen) return GL_FALSE; // We don't include IDCMP flags. The user can change this with // a call to ModifyIDCMP. context->w3dWindow = OpenWindowTags(NULL, WA_PubScreen, (ULONG)context->w3dScreen, WA_InnerWidth, (ULONG)w, WA_InnerHeight, (ULONG)h, WA_Left, 30, WA_Top, 30, WA_Title, (ULONG)"MiniGL Display", WA_DragBar, TRUE, WA_DepthGadget, TRUE, WA_Flags, WFLG_ACTIVATE|WFLG_REPORTMOUSE|WFLG_RMBTRAP, TAG_DONE); if (!context->w3dWindow) goto Duh; context->BufNr = 0; // The drawing buffer context->NumBuffers = 0; // Indicates we're using a window context->DoSync = GL_TRUE; // Enable sync'ing context->w3dBitMap = AllocBitMap(w,h,8,BMF_MINPLANES|BMF_DISPLAYABLE, context->w3dWindow->RPort->BitMap); if (!context->w3dBitMap) goto Duh; context->w3dRastPort = malloc(sizeof(struct RastPort)); if (!context->w3dRastPort) { printf("Error: unable to allocate rastport memory\n"); goto Duh; } InitRastPort(context->w3dRastPort); context->w3dRastPort->BitMap = context->w3dBitMap; tags[0].ti_Tag = W3D_CC_BITMAP; tags[0].ti_Data = (ULONG)(context->w3dBitMap); tags[1].ti_Tag = W3D_CC_DRIVERTYPE; tags[1].ti_Data = W3D_DRIVER_BEST; tags[2].ti_Tag = W3D_CC_FAST; tags[2].ti_Data = FALSE; tags[3].ti_Tag = W3D_CC_YOFFSET; tags[3].ti_Data = 0; tags[4].ti_Tag = W3D_CC_GLOBALTEXENV; tags[4].ti_Data = TRUE; tags[5].ti_Tag = TAG_DONE; context->w3dContext = W3D_CreateContext(&CError, tags); if (!context->w3dContext || CError != W3D_SUCCESS) { switch(CError) { case W3D_ILLEGALINPUT: printf("Illegal input to CreateContext function\n"); break; case W3D_NOMEMORY: printf("Out of memory\n"); break; case W3D_NODRIVER: printf("No suitable driver found\n"); break; case W3D_UNSUPPORTEDFMT: printf("Supplied bitmap cannot be handled by Warp3D\n"); break; case W3D_ILLEGALBITMAP: printf("Supplied bitmap not properly initialized\n"); break; default: printf("An error has occured... gosh\n"); } goto Duh; } /* ** Set up a few initial states ** We always enable scissoring and dithering, since it looks better ** on 16 bit displays. ** We also set shading to smooth (Gouraud). */ W3D_SetState(context->w3dContext, W3D_DITHERING, W3D_ENABLE); W3D_SetState(context->w3dContext, W3D_SCISSOR, W3D_ENABLE); W3D_SetState(context->w3dContext, W3D_GOURAUD, W3D_ENABLE); W3D_SetState(context->w3dContext, W3D_PERSPECTIVE, W3D_ENABLE); /* ** Allocate the ZBuffer. */ result = W3D_AllocZBuffer(context->w3dContext); switch(result) { case W3D_NOGFXMEM: printf("No ZBuffer: Memory shortage\n"); break; case W3D_NOZBUFFER: printf("No ZBuffer: Operation not supported\n"); break; case W3D_NOTVISIBLE: printf("No ZBuffer: Screen is not visible\n"); break; } W3D_SetState(context->w3dContext, W3D_ZBUFFER, W3D_DISABLE); W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE); W3D_SetZCompareMode(context->w3dContext, W3D_Z_LESS); EraseRect(context->w3dWindow->RPort, context->w3dWindow->BorderLeft, context->w3dWindow->BorderTop, context->w3dWindow->Width-context->w3dWindow->BorderLeft-context->w3dWindow->BorderRight-1, context->w3dWindow->Height-context->w3dWindow->BorderTop-context->w3dWindow->BorderBottom-1); GLScissor(context, 0,0, w,h); context->w3dLocked = GL_FALSE; /* ** Select a texture format that needs no conversion */ //FIXME:Really do it. This is lame context->w3dFormat = W3D_A1R5G5B5; context->w3dAlphaFormat = W3D_A4R4G4B4; context->w3dBytesPerTexel = 2; return GL_TRUE; Duh: if (context->w3dWindow) { CloseWindow(context->w3dWindow); context->w3dWindow = NULL; } if (context->w3dScreen) { UnlockPubScreen(NULL, context->w3dScreen); context->w3dScreen = NULL; } if (context->w3dBitMap) { FreeBitMap(context->w3dBitMap); } if (context->w3dRastPort) { free(context->w3dRastPort); } return GL_FALSE; } void MGLResizeContext(GLcontext context, GLsizei width, GLsizei height) { if (!context->w3dBitMap) { vid_ReopenDisplay(context, (int)width, (int)height); context->w3dChipID = context->w3dContext->CurrentChip; } } void *MGLGetWindowHandle(GLcontext context) { return context->w3dWindow; } void mglChooseVertexBufferSize(int size) { newVertexBufferSize = size; } void mglChooseTextureBufferSize(int size) { newTextureBufferSize = size; } void mglChooseNumberOfBuffers(int number) { newNumberOfBuffers = number; } void mglChoosePixelDepth(int depth) { newPixelDepth = depth; } void mglProposeCloseDesktop(GLboolean closeme) { clw = closeme; } void mglProhibitMipMapping(GLboolean flag) { newNoMipMapping = flag; } void mglProhibitAlphaFallback(GLboolean flag) { newNoFallbackAlpha = flag; } void mglChooseWindowMode(GLboolean flag) { newWindowMode = flag; } void GLClearColor(GLcontext context, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { //LOG(2, glClearColor, "%f %f %f %f", red,green,blue,alpha); red *= 255.0; green *= 255.0; blue *= 255.0; alpha *= 255.0; context->ClearColor = ((GLubyte)(alpha)<<24) + ((GLubyte)(red)<<16) + ((GLubyte)(green)<<8) + ((GLubyte)(blue)); } void GLDepthMask(GLcontext context, GLboolean flag) { //LOG(2, glDepthMask, "%d", flag); if (flag == GL_FALSE) W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_DISABLE); else W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE); context->DepthMask = flag; } void GLDepthFunc(GLcontext context, GLenum func) { ULONG wFunc = W3D_Z_LESS; //LOG(2, glDepthFunc, "%d", func); switch(func) { case GL_NEVER: wFunc = W3D_Z_NEVER; break; case GL_LESS: wFunc = W3D_Z_LESS; break; case GL_EQUAL: wFunc = W3D_Z_EQUAL; break; case GL_LEQUAL: wFunc = W3D_Z_LEQUAL; break; case GL_GREATER: wFunc = W3D_Z_GREATER; break; case GL_NOTEQUAL: wFunc = W3D_Z_NOTEQUAL; break; case GL_GEQUAL: wFunc = W3D_Z_GEQUAL; break; case GL_ALWAYS: wFunc = W3D_Z_ALWAYS; break; default: GLFlagError(context, 1, GL_INVALID_ENUM); break; } W3D_SetZCompareMode(context->w3dContext, wFunc); } void GLClearDepth(GLcontext context, GLclampd depth) { //LOG(2, glClearDepth, "%f", depth); context->ClearDepth = (W3D_Double)depth; } void GLClear(GLcontext context, GLbitfield mask) { //LOG(1, glClear, "%d", mask); if (context->w3dLocked == GL_FALSE) W3D_LockHardware(context->w3dContext); if (mask & GL_COLOR_BUFFER_BIT) { W3D_ClearDrawRegion(context->w3dContext, context->ClearColor); } if (mask & GL_DEPTH_BUFFER_BIT) { W3D_ClearZBuffer(context->w3dContext, &(context->ClearDepth)); } if (context->w3dLocked == GL_FALSE) W3D_UnLockHardware(context->w3dContext); } #ifdef AUTOMATIC_LOCKING_ENABLE void MGLLockMode(GLcontext context, GLenum lockMode) { context->LockMode = lockMode; } #endif GLboolean MGLLockBack(GLcontext context, MGLLockInfo *info) { ULONG error; if (context->w3dLocked == GL_TRUE) { error = W3D_SUCCESS; } else { error = W3D_LockHardware(context->w3dContext); } if (error != W3D_SUCCESS) { return GL_FALSE; } else { context->w3dLocked = GL_TRUE; TMA_Start(&(context->LockTime)); if (info) { info->width = context->w3dContext->width; info->height = context->w3dContext->height; info->depth = context->w3dContext->depth; info->pixel_format = context->w3dContext->format; info->base_address = context->w3dContext->drawmem; info->pitch = context->w3dContext->bprow; } } return GL_TRUE; } GLboolean MGLLockDisplay(GLcontext context) { ULONG error; //LOG(1, mglLockDisplay, ""); #ifndef AUTOMATIC_LOCKING_ENABLE if (context->w3dLocked == GL_TRUE) return GL_TRUE; error = W3D_LockHardware(context->w3dContext); if (error == W3D_SUCCESS) { context->w3dLocked = GL_TRUE; return GL_TRUE; } else { switch(error) { case W3D_NOTVISIBLE: printf("[MGLLockDisplay] Bitmap not visible\n"); break; default: printf("[MGLLockDisplay] Error %d while locking\n", error); break; } return GL_FALSE; } #else if (context->w3dLocked == GL_TRUE) return GL_TRUE; // nothing to do if we are already locked switch(context->LockMode) { case MGL_LOCK_MANUAL: error = W3D_LockHardware(context->w3dContext); if (error == W3D_SUCCESS) { context->w3dLocked = GL_TRUE; return GL_TRUE; } break; case MGL_LOCK_AUTOMATIC: // These modes do not require the lock right here. case MGL_LOCK_SMART: return GL_TRUE; break; } printf("[MGLLockDisplay] Unable to lock\n"); return GL_FALSE; // If we got here, there was an error #endif } void MGLUnlockDisplay(GLcontext context) { //LOG(1, mglUnlockDisplay, ""); #ifndef AUTOMATIC_LOCKING_ENABLE if (context->w3dLocked == GL_FALSE) return; W3D_UnLockHardware(context->w3dContext); context->w3dLocked = GL_FALSE; #else if (context->w3dLocked == GL_FALSE) return; switch(context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: case MGL_LOCK_MANUAL: W3D_UnLockHardware(context->w3dContext); break; } context->w3dLocked = GL_FALSE; #endif } void MGLEnableSync(GLcontext context, GLboolean enable) { context->DoSync = enable; } void MGLSwitchDisplay(GLcontext context) { int nowbuf = context->BufNr; MGLUnlockDisplay(context); if (!context->w3dBitMap) // Fullscreen mode { context->BufNr++; if (context->BufNr == context->NumBuffers) context->BufNr = 0; /* ** At this place, nowbuf contains the buffer we where drawing to. ** BufNr is the next drawing buffer. ** We switch nowbof to the be the display buffer, and set ** the draw region to the new BufNr */ // FIXME: This may cause a context switch orgy, maybe make it 68k // Make nowbuf current display context->Buffers[nowbuf]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; #ifdef USE_68K_SWITCHER if (context->SwitcherTask) { ULONG *where = (ULONG *)context->SwitcherMemArea; where[0] = (ULONG)context->w3dScreen; where[1] = (ULONG)context->Buffers[nowbuf]; Signal68K(context->SwitcherTask, SIGBREAKF_CTRL_F); } #else while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[nowbuf])); #endif // Make BufNr the new draw area W3D_SetDrawRegion(context->w3dContext, context->Buffers[context->BufNr]->sb_BitMap, 0, &(context->scissor)); if (context->DoSync) { struct ViewPort *vp = &(context->w3dScreen->ViewPort); WaitBOVP(vp); } } else { // Windowed mode ClipBlit(context->w3dRastPort,0,0, context->w3dWindow->RPort, context->w3dWindow->BorderLeft, context->w3dWindow->BorderTop, context->w3dWindow->Width-context->w3dWindow->BorderLeft-context->w3dWindow->BorderRight, context->w3dWindow->Height-context->w3dWindow->BorderTop-context->w3dWindow->BorderBottom, 0xC0); } } GLboolean MGLInitContext(GLcontext context) { int i; context->CurrentPrimitive = GL_BASE; context->CurrentError = GL_NO_ERROR; context->VertexBuffer = malloc(sizeof(MGLVertex)*newVertexBufferSize); if (!context->VertexBuffer) return GL_FALSE; context->VertexBufferSize = (GLuint)newVertexBufferSize; context->VertexBufferPointer= 0; context->TexBufferSize = newTextureBufferSize; context->w3dTexBuffer = malloc(sizeof(W3D_Texture *) * newTextureBufferSize); if (!context->w3dTexBuffer) return GL_FALSE; context->w3dTexMemory = malloc(sizeof(GLubyte *) * newTextureBufferSize); if (!context->w3dTexMemory) return GL_FALSE; context->CurrentBinding = 0; // Indicate unbound texture object for (i=0; iw3dTexBuffer[i] = NULL; context->w3dTexMemory[i] = NULL; } context->CurrentTexS = context->CurrentTexT = 0.0; context->CurrentTexQ = 1.0; context->CurrentTexQValid = GL_FALSE; context->PackAlign = context->UnpackAlign = 4; context->AlphaTest_State = GL_FALSE; context->Blend_State = GL_FALSE; context->Texture2D_State = GL_FALSE; context->TextureGenS_State = GL_FALSE; context->TextureGenT_State = GL_FALSE; context->Fog_State = GL_FALSE; context->Scissor_State = GL_FALSE; context->CullFace_State = GL_FALSE; context->DepthTest_State = GL_FALSE; context->PointSmooth_State = GL_FALSE; context->Dither_State = GL_TRUE; context->ZOffset_State = GL_FALSE; context->FogDirty = GL_FALSE; context->FogStart = 1.0; context->FogEnd = 0.0; context->TexEnv = GL_MODULATE; context->MinFilter = GL_NEAREST; context->MagFilter = GL_NEAREST; context->WrapS = GL_REPEAT; context->WrapT = GL_REPEAT; context->w3dFog.fog_start = 1.0; context->w3dFog.fog_end = 0.1; context->w3dFog.fog_density = 1.0; context->w3dFog.fog_color.r = 0.0; context->w3dFog.fog_color.g = 0.0; context->w3dFog.fog_color.b = 0.0; context->FogRange = 1.0; context->CurrentCullFace = GL_BACK; context->CurrentFrontFace = GL_CCW; context->ShadeModel = GL_SMOOTH; context->DepthMask = GL_TRUE; context->ClearDepth = 1.0; #ifdef AUTOMATIC_LOCKING_ENABLE context->LockMode = MGL_LOCK_MANUAL; #endif context->NoMipMapping = newNoMipMapping; context->NoFallbackAlpha = newNoFallbackAlpha; context->Idle = NULL; context->MouseHandler = NULL; context->SpecialHandler = NULL; context->KeyHandler = NULL; context->SrcAlpha = 0; context->DstAlpha = 0; context->AlphaFellBack = GL_FALSE; context->WOne_Hint = GL_FALSE; context->ZOffset = 0.0; context->PaletteData = malloc(4*256); context->PaletteSize = 0; context->PaletteFormat = 0; /* Begin Joe Sera Sept 23 2000 */ context->CurPolygonMode = GL_FILL ; context->CurShadeModel = GL_SMOOTH ; context->CurBlendSrc = GL_ONE ; context->CurBlendDst = GL_ZERO ; context->CurUnpackRowLength = 0 ; context->CurUnpackSkipPixels = 0 ; context->CurUnpackSkipRows = 0 ; /* End Joe Sera Sept 23 2000 */ /* Begin Joe Sera Oct. 21, 2000 */ context->CurWriteMask = GL_TRUE ; context->CurDepthTest = GL_FALSE ; /* End Joe Sera Oct. 21, 2000 */ /* Vertex array stuff */ context->ClientState = 0; context->DrawElementsHook = 0; context->DrawArraysHook = 0; GLMatrixInit(context); return GL_TRUE; } void *MGLCreateContext(int offx, int offy, int w, int h) { GLcontext context; context = malloc(sizeof(struct GLcontext_t)); if (!context) { printf("Error: Can't get %d bytes of memory for context\n", sizeof(struct GLcontext_t)); return NULL; } memset(context, 0, sizeof(struct GLcontext_t)); if (newWindowMode == GL_FALSE) { if (GL_FALSE == vid_OpenDisplay(context, w,h, MGL_SM_BESTMODE)) { vid_CloseDisplay(context); free(context); printf("Error: opening of display failed\n"); return NULL; } } else { if (GL_FALSE == vid_OpenWindow(context, w,h)) { vid_CloseWindow(context); free(context); printf("Error: opening of display failed\n"); return NULL; } } if (GL_FALSE == MGLInitContext(context)) { printf("Error: initalisation of context failed\n"); MGLDeleteContext(context); return NULL; } GLDepthRange(context, 0.0, 1.0); GLViewport(context, offx, offy, w, h); GLClearColor(context, 0.0, 0.0, 0.0, 1.0); // Hey, folks, I can do that because I know what I am doing. // You should never read fields from the W3D context that are not // marked as readable... context->w3dChipID = context->w3dContext->CurrentChip; // Start the switcher thread #ifdef USE_68K_SWITCHER if (!context->w3dBitMap) // Fullscreen mode { volatile ULONG *mem; context->SwitcherTask = Create68kTask("MiniGL buffer switch thread", 0, (APTR)SwitcherCode, 20000); context->SwitcherMemArea = AllocVecPPC(20, MEMF_CACHEOFF|MEMF_WRITETHROUGH|MEMF_CHIP, 0); if (!context->SwitcherTask || !context->SwitcherMemArea) { MGLDeleteContext(context); printf("Error: Switcher initialization failed\n"); return 0; } context->SwitcherTask->tc_UserData = context->SwitcherMemArea; mem = (ULONG *)context->SwitcherMemArea; *mem = (ULONG)IntuitionBase; Signal(context->SwitcherTask, SIGBREAKF_CTRL_E); // Enforce cache flush } #endif return context; } void MGLDeleteContext(GLcontext context) { GLint current,peak; #ifdef USE_68K_SWITCHER if (context->SwitcherTask) Signal68K(context->SwitcherTask, SIGBREAKF_CTRL_C); #endif if (context->w3dBitMap) vid_CloseWindow(context); else vid_CloseDisplay(context); if (context->VertexBuffer) free(context->VertexBuffer); if (context->w3dTexBuffer) free(context->w3dTexBuffer); MGLTexMemStat(context, ¤t, &peak); if (CyberGfxBase) CloseLibrary(CyberGfxBase); CyberGfxBase = NULL; #ifdef USE_68K_SWITCHER if (context->SwitcherMemArea) FreeVecPPC(context->SwitcherMemArea); #endif free(context); } #define ED (flag == GL_TRUE?W3D_ENABLE:W3D_DISABLE) void MGLSetState(GLcontext context, GLenum cap, GLboolean flag) { //LOG(2, mglSetState, "(Enable/Disable) %d -> %d\n", cap, flag); switch(cap) { case GL_ALPHA_TEST: context->AlphaTest_State = flag; W3D_SetState(context->w3dContext, W3D_ALPHATEST, ED); break; case GL_BLEND: context->Blend_State = flag; W3D_SetState(context->w3dContext, W3D_BLENDING, ED); break; case GL_TEXTURE_2D: context->Texture2D_State = flag; W3D_SetState(context->w3dContext, W3D_TEXMAPPING, ED); break; case GL_TEXTURE_GEN_S: context->TextureGenS_State = flag; break; case GL_TEXTURE_GEN_T: context->TextureGenT_State = flag; break; case GL_FOG: context->FogDirty = GL_TRUE; context->Fog_State = flag; W3D_SetState(context->w3dContext, W3D_FOGGING, ED); break; case GL_SCISSOR_TEST: context->Scissor_State = flag; W3D_SetState(context->w3dContext, W3D_SCISSOR, ED); break; case GL_CULL_FACE: context->CullFace_State = flag; break; case GL_DEPTH_WRITEMASK: context->CurWriteMask = flag ; break ; case GL_DEPTH_TEST: context->CurDepthTest = flag ; context->DepthTest_State = flag; W3D_SetState(context->w3dContext, W3D_ZBUFFER, ED); if (flag == GL_TRUE) { if (context->DepthMask) W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE); } else { W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_DISABLE); } break; case GL_DITHER: context->Dither_State = flag; W3D_SetState(context->w3dContext, W3D_DITHERING, ED); break; case GL_POINT_SMOOTH: context->PointSmooth_State = flag; W3D_SetState(context->w3dContext, W3D_ANTI_POINT, ED); break; case MGL_PERSPECTIVE_MAPPING: W3D_SetState(context->w3dContext, W3D_PERSPECTIVE, ED); break; case MGL_Z_OFFSET: context->ZOffset_State = flag; break; default: break; } } #undef ED GLint mglGetSupportedScreenModes(MGLScreenModeCallback CallbackFn) { W3D_ScreenMode *Modes = W3D_GetScreenmodeList(); W3D_ScreenMode *Cursor; MGLScreenMode sMode; GLboolean retval; if (Modes == NULL) { return MGL_SM_BESTMODE; } Cursor = Modes; while (Cursor) { sMode.id = (GLint)Cursor->ModeID; sMode.width = (GLint)Cursor->Width; sMode.height = (GLint)Cursor->Height; sMode.bit_depth = (GLint)Cursor->Depth; strncpy(sMode.mode_name, Cursor->DisplayName, MGL_MAX_MODE); retval = CallbackFn(&sMode); if (retval == GL_TRUE) { W3D_FreeScreenmodeList(Modes); return sMode.id; } Cursor = Cursor->Next; } W3D_FreeScreenmodeList(Modes); return MGL_SM_BESTMODE; } void *MGLCreateContextFromID(GLint id, GLint *width, GLint *height) { GLint w,h; GLcontext context; context = malloc(sizeof(struct GLcontext_t)); if (!context) { printf("Error: Can't get %d bytes of memory for context\n", sizeof(struct GLcontext_t)); return NULL; } memset(context, 0, sizeof(struct GLcontext_t)); if (id == MGL_SM_WINDOWMODE) newWindowMode = GL_TRUE; if (newWindowMode == GL_FALSE) { if (GL_FALSE == vid_OpenDisplay(context, -1,-1, (ULONG)id)) { vid_CloseDisplay(context); free(context); printf("Error: opening of display failed\n"); return NULL; } } else { // Use the other context creation function for Windowed mode. return NULL; } if (GL_FALSE == MGLInitContext(context)) { printf("Error: initalisation of context failed\n"); MGLDeleteContext(context); return NULL; } w = context->w3dScreen->Width; h = context->w3dScreen->Height; *width = w; *height = h; GLDepthRange(context, 0.0, 1.0); GLViewport(context, 0, 0, w, h); GLClearColor(context, 0.0, 0.0, 0.0, 1.0); // Hey, folks, I can do that because I know what I am doing. // You should never read fields from the W3D context that are not // marked as readable... context->w3dChipID = context->w3dContext->CurrentChip; return context; }