/* * $Id$ * * $Date$ * $Revision$ * * (C) 1997-2008 The MiniGL team * All rights reserved * * This file is part of the MiniGL library project * See the file Licence.txt for more details * */ #include "displaylists.h" #include "sysinc.h" #include #include #include #include #include #include "smartlock.h" #include "util.h" extern void buf_InternalDrawBuffer(GLcontext context, GLenum mode); extern void buf_InternalReadBuffer(GLcontext context, GLenum mode); extern void buf_SetFrontBuffer(GLcontext context, void *bitmap, GLboolean free); extern void buf_SetBackBuffer(GLcontext context, void *bitmap, GLboolean free); extern GLboolean buf_SetAuxBuffer(GLcontext context, GLenum buffer, void *bitmap, GLboolean free); extern void buf_FreeBuffer(GLcontext context, GLbuffer *buffer); extern GLboolean buf_AllocBuffer(GLcontext context, GLbuffer *buffer, int width, int height, struct BitMap *friend); extern void tex_FreeTextures(GLcontext); extern void RebindTextures(GLcontext context); #define min(x, y) ((x) < (y) ? (x) : (y)) static void vid_CloseOrUnlockScreen(GLcontext context) { if (!context->w3dScreen) { return; } if (context->w3dScreenLocked) { IIntuition->UnlockPubScreen(NULL, context->w3dScreen); } else { IIntuition->CloseScreen(context->w3dScreen); } context->w3dScreen = 0; } static void vid_Pointer(GLcontext context, struct Window *window) { if (!context->MousePointer) { context->MousePointer = AllocVecInternal(12, MEMF_CLEAR|MEMF_CHIP); } if (window) { IIntuition->SetPointer(window, context->MousePointer, 1, 16, 0, 0); } } static void vid_DeletePointer(GLcontext context, struct Window *window) { if (window) { IIntuition->ClearPointer(window); } FreeVecInternalCheckAndClear((void**)&context->MousePointer); } void *cgl_GetWindowHandle(struct GLContextIFace *Self) { GLcontext context = GET_INSTANCE(Self); Self->UnlockDisplay(); return context->w3dWindow; } void cgl_GrabFocus(struct GLContextIFace *Self, GLboolean yesno) { GLcontext context = GET_INSTANCE(Self); context->GrabMouse = yesno; if (yesno == GL_FALSE) { IIntuition->SetWindowAttrs( context->w3dWindow, WA_GrabFocus, 0, WA_MouseLimits, NULL, TAG_DONE ); } } GLboolean cgl_LockBack(struct GLContextIFace *Self, MGLLockInfo *info) { GLcontext context = GET_INSTANCE(Self); GLboolean isLocked; if (context->LockMode == MGL_LOCK_SMART) { isLocked = smartlock_beginDraw(context->smartLock); } else { if (context->w3dLocked == GL_TRUE) { isLocked = GL_TRUE; } else { if (IWarp3D->W3D_LockHardware(context->w3dContext) == W3D_SUCCESS) { isLocked = GL_TRUE; } else { isLocked = GL_FALSE; } } } if (isLocked == GL_FALSE) { return GL_FALSE; } else { 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 vid_OpenDisplay(GLcontext context, int width, int height, uint32 id) { uint32 ModeID; int i; int w = width, h = height; uint32 pad; if (!context) { return GL_FALSE; } if (id != MGL_SM_BESTMODE && id != MGL_SM_WINDOWMODE) { ModeID = id; dprintf("Using given mode id = %p\n", ModeID); } else { dprintf("Trying to determine best mode id\n"); ModeID = IWarp3D->W3D_BestModeIDTags( W3D_BMI_WIDTH, w, W3D_BMI_HEIGHT, h, W3D_BMI_DEPTH, context->Params.newPixelDepth, TAG_DONE ); dprintf("Mode ID = %p\n", ModeID); } if (ModeID == INVALID_ID) { return GL_FALSE; } dprintf("ModeID: %u\n", ModeID); /* The Voodoo driver has a bug that allows it to open a screen bitmap that * is not a multiple of 64. This works for 2d operations, but 3d operations * require a 64 pixel alignment. We pad the width to the next multiple of * 64 */ pad = w; if (w % 64 != 0) { pad = ((w/64)+1)*64; } uint16 emptyPens[] = {~0}; // Allow the new screen to use the 3D look context->w3dScreen = IIntuition->OpenScreenTags( NULL, SA_Depth, 8L, SA_DisplayID, ModeID, SA_ShowTitle, FALSE, SA_Draggable, FALSE, SA_Width, pad, SA_Pens, emptyPens, TAG_DONE); context->w3dScreenLocked = GL_FALSE; if (context->Params.clw == GL_TRUE) { context->DoOpenWorkbench = IIntuition->CloseWorkBench(); } else { context->DoOpenWorkbench = FALSE; } 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 = IIntuition->OpenWindowTags( NULL, WA_CustomScreen, context->w3dScreen, WA_Width, context->w3dScreen->Width, WA_Height, 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] = IIntuition->AllocScreenBuffer(context->w3dScreen, NULL, SB_SCREEN_BITMAP); if (!context->Buffers[0]) { dprintf("Error: Can't create screen buffer 0\n"); goto Duh; } for (i=1; iParams.newNumberOfBuffers; i++) { context->Buffers[i] = IIntuition->AllocScreenBuffer(context->w3dScreen, NULL, 0); if (!context->Buffers[i]) { dprintf("Error: Can't create screen buffer %d\n", i); goto Duh; } } context->NumBuffers = context->Params.newNumberOfBuffers; // So we know the limit context->DoSync = GL_TRUE; // Enable sync'ing context->BufNr = context->NumBuffers > 1 ? 1 : 0; // The drawing buffer IGraphics->SetRGB32(&(context->w3dScreen->ViewPort), 0, 0x7fffffff,0x7fffffff,0x7fffffff); for (i=0; iNumBuffers; i++) { context->Buffers[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; while (!IIntuition->ChangeScreenBuffer(context->w3dScreen, context->Buffers[i])) { // Empty } IGraphics->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 (!IIntuition->ChangeScreenBuffer(context->w3dScreen, context->Buffers[0])) { // Empty } context->w3dLocked = GL_FALSE; vid_Pointer(context, context->w3dWindow); /* Setup front and back buffer */ buf_SetFrontBuffer(context, context->Buffers[0]->sb_BitMap, GL_FALSE); buf_SetBackBuffer(context, context->Buffers[context->BufNr]->sb_BitMap, GL_FALSE); context->fullScreen = GL_TRUE; context->windowed = GL_FALSE; return GL_TRUE; Duh: for (i=0; iParams.newNumberOfBuffers; i++) { if (context->Buffers[i]) { IIntuition->FreeScreenBuffer(context->w3dScreen, context->Buffers[i]); context->Buffers[i] = NULL; } } if (context->w3dWindow) { IIntuition->CloseWindow(context->w3dWindow); context->w3dWindow = NULL; } vid_CloseOrUnlockScreen(context); return GL_FALSE; } GLboolean vid_OpenWindow(GLcontext context, int w, int h, int left, int top) { dprintf("context = %p\n", context); if (!context) { return GL_FALSE; } context->w3dScreen = IIntuition->LockPubScreen(NULL); if (!context->w3dScreen) { return GL_FALSE; } context->w3dScreenLocked = GL_TRUE; /* We don't include IDCMP flags. The user can change this with * a call to ModifyIDCMP. */ context->w3dWindow = IIntuition->OpenWindowTags(NULL, WA_PubScreen, context->w3dScreen, WA_InnerWidth, w, WA_InnerHeight, h, WA_Left, left, WA_Top, top, WA_Title, "MiniGL Display", WA_DragBar, TRUE, WA_DepthGadget, TRUE, WA_Flags, WFLG_ACTIVATE|WFLG_REPORTMOUSE| WFLG_RMBTRAP| (context->Params.newCloseGadget == GL_TRUE ? WFLG_CLOSEGADGET : 0)| (context->Params.newSizeGadget == GL_TRUE ? WFLG_SIZEGADGET : 0), WA_MinWidth, 100, WA_MinHeight, 100, WA_MaxWidth, 2048, WA_MaxHeight, 2048, TAG_DONE ); dprintf("context->w3dWindow = %p\n", context->w3dWindow); if (!context->w3dWindow) { goto Duh; } context->BufNr = 0; // The drawing buffer context->NumBuffers = 1; context->DoSync = GL_TRUE; // Enable sync'ing dprintf("Allocating bitmap\n"); if ( !buf_AllocBuffer( context, &context->currentFrontBuffer, w, h, context->w3dWindow->RPort->BitMap ) ) { goto Duh; } if (context->Params.newNumberOfBuffers > 1) { context->NumBuffers = 2; if ( !buf_AllocBuffer( context, &context->currentBackBuffer, w, h, context->w3dWindow->RPort->BitMap ) ) { goto Duh; } } dprintf("Clearing window rectangle\n"); IGraphics->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->Self->LockMode(MGL_LOCK_SMART); context->w3dLocked = GL_FALSE; context->fullScreen = GL_FALSE; context->windowed = GL_TRUE; dprintf("Success\n"); return GL_TRUE; Duh: dprintf("Failure\n"); if (context->w3dWindow) { IIntuition->CloseWindow(context->w3dWindow); context->w3dWindow = NULL; } if (context->w3dScreen) { IIntuition->UnlockPubScreen(NULL, context->w3dScreen); context->w3dScreen = NULL; } buf_FreeBuffer(context, &context->currentBackBuffer); buf_FreeBuffer(context, &context->currentFrontBuffer); dprintf("Error, returning GL_FALSE\n"); return GL_FALSE; } GLboolean vid_SetBitmap(GLcontext context, struct BitMap *bitMap, int *w, int *h) { if (!context || !bitMap) { return GL_FALSE; } // ##### FIXME! ##### some of this should be in buf_SetFrontBuffer() and buf_SetBackBuffer() context->BufNr = 0; // The drawing buffer context->DoSync = GL_TRUE; // Enable sync'ing *w = IP96->p96GetBitMapAttr(bitMap, P96BMA_WIDTH); *h = IP96->p96GetBitMapAttr(bitMap, P96BMA_HEIGHT); /* Moved to buf_#?Buffer GLbuffer *buffer = &context->currentFrontBuffer; buffer->bitMap = bitMap; buffer->width = *w; buffer->height = *h; buffer->flags &= ~BUF_FREE_BITMAP; IGraphics->InitRastPort(&buffer->rastPort); buffer->rastPort.BitMap = buffer->bitMap; buffer = &context->currentBackBuffer; buffer->bitMap = bitMap; buffer->width = *w; buffer->height = *h; buffer->flags &= ~BUF_FREE_BITMAP; IGraphics->InitRastPort(&buffer->rastPort); buffer->rastPort.BitMap = buffer->bitMap; */ GLboolean relock = GL_FALSE; if (context->w3dLocked == GL_TRUE) { switch(context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: smartlock_forceUnlock(context->smartLock); break; case MGL_LOCK_MANUAL: IWarp3D->W3D_UnLockHardware(context->w3dContext); context->w3dLocked = GL_FALSE; relock = GL_TRUE; break; } } context->fullScreen = GL_FALSE; context->windowed = GL_FALSE; context->NumBuffers = 1; /* Setup front and back buffer */ buf_SetFrontBuffer(context, bitMap, GL_FALSE); buf_SetBackBuffer(context, bitMap, GL_FALSE); if (relock == GL_TRUE) { switch (context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: smartlock_beginDraw(context->smartLock); smartlock_endDraw(context->smartLock); break; case MGL_LOCK_MANUAL: IWarp3D->W3D_LockHardware(context->w3dContext); break; } context->w3dLocked = GL_TRUE; } return GL_TRUE; } GLboolean vid_CreateWarp3DContext(GLcontext context) { uint32 CError; dprintf("Creating Warp3D context\n"); context->w3dContext = IWarp3D->W3D_CreateContextTags( &CError, W3D_CC_BITMAP, context->drawBuffer->bitMap, W3D_CC_DRIVERTYPE, W3D_DRIVER_BEST, W3D_CC_FAST, TRUE, W3D_CC_YOFFSET, 0, W3D_CC_GLOBALTEXENV, TRUE, TAG_DONE ); dprintf("context->w3dContext = %p\n", context->w3dContext); if (!context->w3dContext || CError != W3D_SUCCESS) { switch (CError) { case W3D_ILLEGALINPUT: dprintf("Illegal input to CreateContext function\n"); break; case W3D_NOMEMORY: dprintf("Out of memory\n"); break; case W3D_NODRIVER: dprintf("No suitable driver found\n"); break; case W3D_UNSUPPORTEDFMT: dprintf("Supplied bitmap cannot be handled by Warp3D\n"); break; case W3D_ILLEGALBITMAP: dprintf("Supplied bitmap not properly initialized\n"); break; default: dprintf("An error has occured... gosh\n"); } return GL_FALSE; } return GL_TRUE; } void vid_DestroyWarp3DContext(GLcontext context) { // Ensure that the hardware is not locked if (context->w3dLocked == GL_TRUE) { switch (context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: smartlock_forceUnlock(context->smartLock); break; case MGL_LOCK_MANUAL: IWarp3D->W3D_UnLockHardware(context->w3dContext); break; } context->w3dLocked = GL_FALSE; } //IExec->DebugPrintF("context->w3dContext = %p\n", context->w3dContext); if (context->w3dContext) { //IExec->DebugPrintF("Deleting Warp3D stuffies\n"); IWarp3D->W3D_FreeZBuffer(context->w3dContext); if (context->Params.newStencilBuffer) { IWarp3D->W3D_FreeStencilBuffer(context->w3dContext); } tex_FreeTextures(context); IWarp3D->W3D_DestroyContext(context->w3dContext); context->w3dContext = 0; } } GLboolean vid_AllocDepthStencil(GLcontext context, GLboolean setstate) { /* ** Allocate the ZBuffer. */ GLboolean success = GL_TRUE; uint32 result = IWarp3D->W3D_AllocZBuffer(context->w3dContext); switch(result) { case W3D_NOGFXMEM: dprintf("No ZBuffer: Memory shortage\n"); success = GL_FALSE; break; case W3D_NOZBUFFER: dprintf("No ZBuffer: Operation not supported\n"); success = GL_FALSE; break; case W3D_NOTVISIBLE: dprintf("No ZBuffer: Screen is not visible\n"); success = GL_FALSE; break; } /* * Allocate the Stencil buffer */ if (context->Params.newStencilBuffer) { dprintf("Allocating an S-Buffer\n"); result = IWarp3D->W3D_AllocStencilBuffer(context->w3dContext); switch(result) { case W3D_NOGFXMEM: dprintf("No SBuffer: Memory shortage\n"); context->Params.newStencilBuffer = FALSE; //success = GL_FALSE; break; case W3D_NOSTENCILBUFFER: dprintf("No SBuffer: Operation not supported\n"); context->Params.newStencilBuffer = FALSE; //success = GL_FALSE; break; case W3D_NOTVISIBLE: dprintf("No SBuffer: Screen is not visible\n"); context->Params.newStencilBuffer = FALSE; //success = GL_FALSE; break; default: { uint32 clearval = 0; if (context->w3dLocked == GL_FALSE) { IWarp3D->W3D_LockHardware(context->w3dContext); } IWarp3D->W3D_ClearStencilBuffer(context->w3dContext, &clearval); if (context->w3dLocked == GL_FALSE) { IWarp3D->W3D_UnLockHardware(context->w3dContext); } break; } } } else { dprintf("Not allocating an S-Buffer\n"); } if (setstate) { IWarp3D->W3D_SetState(context->w3dContext, W3D_ZBUFFER, W3D_DISABLE); IWarp3D->W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE); IWarp3D->W3D_SetZCompareMode(context->w3dContext, W3D_Z_LESS); } return success; } void vid_SetDefaultStates(GLcontext context) { /* ** 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). */ IWarp3D->W3D_SetState(context->w3dContext, W3D_DITHERING, W3D_ENABLE); IWarp3D->W3D_SetState(context->w3dContext, W3D_GOURAUD, W3D_ENABLE); IWarp3D->W3D_SetState(context->w3dContext, W3D_PERSPECTIVE, W3D_ENABLE); IWarp3D->W3D_SetState(context->w3dContext, W3D_MULTITEXTURE, W3D_ENABLE); IWarp3D->W3D_SetState(context->w3dContext, W3D_CHROMATEST, W3D_DISABLE); IWarp3D->W3D_SetState(context->w3dContext, W3D_FOG_COORD, W3D_ENABLE); } void vid_CloseCurrentDisplay(GLcontext context) { int i; if (context->fullScreen) { if (context->Buffers[0]) { context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL; while (!IIntuition->ChangeScreenBuffer(context->w3dScreen, context->Buffers[0])) { /* empty */ } } for (i=0; iNumBuffers; i++) { if (context->Buffers[i]) { IIntuition->FreeScreenBuffer(context->w3dScreen, context->Buffers[i]); } context->Buffers[i] = NULL; } vid_DeletePointer(context, context->w3dWindow); if (context->w3dWindow) { IIntuition->CloseWindow(context->w3dWindow); context->w3dWindow = NULL; } vid_CloseOrUnlockScreen(context); if (context->DoOpenWorkbench){ IIntuition->OpenWorkBench(); } } if (context->windowed) { if (context->w3dWindow) { IIntuition->CloseWindow(context->w3dWindow); context->w3dWindow = NULL; } vid_CloseOrUnlockScreen(context); } /* Free all buffers. The buffer's flags indicate whether they need to be * freed or not, so we can simply call the function unconditionally */ buf_FreeBuffer(context, &context->currentFrontBuffer); buf_FreeBuffer(context, &context->currentBackBuffer); for (i = 0; i < MGL_MAX_AUX_BUFFERS; i++) { buf_FreeBuffer(context, &context->currentAuxBuffer[i]); } context->windowed = GL_FALSE; context->fullScreen = GL_FALSE; } void cgl_SwitchDisplay(struct GLContextIFace *Self) { GLcontext context = GET_INSTANCE(Self); int nowbuf = context->BufNr; Self->UnlockDisplay(); #if 1 if (context->statFrame != 0 && context->enableFPS) { struct TimeVal sub; if (context->windowed || context->fullScreen) { char buffer[512]; /* Display last frame's data */ sprintf(buffer,"[%4.4f/%4.4f fps] [%.2f/%.2f µs] [%.2f/%.2f µs] ", context->currentFPS, context->averageFPS, context->currentFrameTime, context->averageFrameTime, context->currentSwapTime, context->averageSwapTime ); IGraphics->SetAPen(context->w3dWindow->RPort, 2); IGraphics->SetBPen(context->w3dWindow->RPort, 0); IGraphics->SetDrMd(context->w3dWindow->RPort, JAM1); IGraphics->Move( context->w3dWindow->RPort, context->w3dWindow->BorderRight+10, context->w3dWindow->BorderTop+10 ); IGraphics->Text(context->w3dWindow->RPort, buffer, strlen(buffer)); } ITimer->GetSysTime(&context->frameEndTime); sub = context->frameEndTime; ITimer->SubTime(&sub, &context->frameStartTime); context->currentFrameTime = sub.Microseconds + 1000000.0 * sub.Seconds; } #endif if (context->fullScreen) { /* Make the current buffer the front buffer */ buf_SetFrontBuffer(context, context->Buffers[context->BufNr]->sb_BitMap, GL_FALSE); if (context->NumBuffers > 1) { context->BufNr++; if (context->BufNr >= context->NumBuffers) { context->BufNr = 0; } } while (!IIntuition->ChangeScreenBuffer(context->w3dScreen, context->Buffers[nowbuf])) { /* empty */ } // Make BufNr the new draw area IWarp3D->W3D_SetDrawRegion(context->w3dContext, context->Buffers[context->BufNr]->sb_BitMap, 0, &(context->w3dScissor)); buf_SetBackBuffer(context, context->Buffers[context->BufNr]->sb_BitMap, GL_FALSE); if (context->DoSync) { struct ViewPort *vp = &(context->w3dScreen->ViewPort); IGraphics->WaitBOVP(vp); } } else if (context->windowed) { // Windowed mode if (context->fbDirty) { WORD width = min(context->w3dWindow->Width - context->w3dWindow->BorderLeft - context->w3dWindow->BorderRight, context->drawBuffer->width); WORD height = min(context->w3dWindow->Height - context->w3dWindow->BorderTop - context->w3dWindow->BorderBottom, context->drawBuffer->height); IGraphics->ClipBlit(&context->drawBuffer->rastPort, 0, 0, context->w3dWindow->RPort, context->w3dWindow->BorderLeft, context->w3dWindow->BorderTop, width, height, 0xC0 ); context->fbDirty = GL_FALSE; } /* Swap the buffers if we have more than one */ if (context->NumBuffers > 1) { GLbuffer temp = context->currentFrontBuffer; context->currentFrontBuffer = context->currentBackBuffer; context->currentBackBuffer = temp; } IWarp3D->W3D_SetDrawRegion(context->w3dContext, context->drawBuffer->bitMap, 0, &(context->w3dScissor)); buf_InternalDrawBuffer(context, context->color_buffer.DrawBuffer); buf_InternalReadBuffer(context, context->color_buffer.ReadBuffer); if (context->GrabMouse == GL_TRUE) { struct IBox b; b.Left = context->w3dWindow->BorderLeft; b.Top = context->w3dWindow->BorderTop; b.Width = context->w3dWindow->Width - context->w3dWindow->BorderLeft - context->w3dWindow->BorderRight; b.Height = context->w3dWindow->Height - context->w3dWindow->BorderTop - context->w3dWindow->BorderBottom; IIntuition->SetWindowAttrs( context->w3dWindow, WA_GrabFocus, 100, WA_MouseLimits, &b, TAG_DONE ); } } #if 1 if (context->enableFPS) { struct TimeVal diff; /* Start time for new frame */ ITimer->GetSysTime(&context->frameStartTime); /* frameStartTime - frameEndTime is the time used for swapping the * buffer */ diff = context->frameStartTime; ITimer->SubTime(&diff, &context->frameEndTime); context->currentSwapTime = diff.Microseconds + 1000000.0 * diff.Seconds; if (context->statFrame != 0) { /* Calculate current fps */ context->currentFPS = (float) ((double)1000000.0 / (double)context->currentFrameTime); context->accumulatedFPS += context->currentFPS; context->averageFPS = context->accumulatedFPS / (float)context->statFrame; context->accumulatedFrameTime += context->currentFrameTime; context->averageFrameTime = context->accumulatedFrameTime / (float)context->statFrame; context->accumulatedSwapTime += context->currentSwapTime; context->averageSwapTime = context->accumulatedSwapTime / (float)context->statFrame; if (context->fullScreen || context->windowed) { char buffer[512]; IUtility->SNPrintf(buffer, 510, "[%4.4f/%4.4f fps] [%.2f/%.2f �s] [%.2f/%.2f �s] ", context->currentFPS, context->averageFPS, context->currentFrameTime, context->averageFrameTime, context->currentSwapTime, context->averageSwapTime); IGraphics->SetAPen(context->w3dWindow->RPort, 2); IGraphics->SetBPen(context->w3dWindow->RPort, 0); IGraphics->SetDrMd(context->w3dWindow->RPort, JAM1); IGraphics->Move(context->w3dWindow->RPort, context->w3dWindow->BorderRight+10, context->w3dWindow->BorderTop+10); IGraphics->Text(context->w3dWindow->RPort, buffer, strlen(buffer)); } } else { context->averageFPS = context->currentFPS; context->averageFrameTime = context->currentFrameTime; context->averageSwapTime = context->averageSwapTime; context->accumulatedFPS = context->currentFPS; context->accumulatedFrameTime = context->currentFrameTime; context->accumulatedSwapTime = context->averageSwapTime; } context->statFrame++; } #endif } void vid_MaybeBlitFrontBuffer(GLcontext context) { if (context->windowed) { if (context->fbDirty && context->drawBuffer == &context->currentFrontBuffer) { /* We're drawing into the front buffer */ IWarp3D->W3D_FlushFrame(context->w3dContext); IWarp3D->W3D_WaitIdle(context->w3dContext); IGraphics->ClipBlit(&context->drawBuffer->rastPort, 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); context->fbDirty = GL_FALSE; } } if ( context->fbDirtyHook && context->fbDirty && (context->drawBuffer == &context->currentFrontBuffer) ) { /* First ensure that the render operations have been flushed and completed */ IWarp3D->W3D_FlushFrame(context->w3dContext); IWarp3D->W3D_WaitIdle(context->w3dContext); /* Call The fbDirtyHook */ context->fbDirtyHook((void *)context,(void *)context->fbDirtyHookData); context->fbDirty = GL_FALSE; } } void cgl_SetBitmap(struct GLContextIFace *Self, void *bitmap) { struct TagItem tagList[] = {{MGLCC_Bitmap, (uint32)bitmap}, {TAG_DONE, TAG_DONE}}; Self->MGLUpdateContext(tagList); } void cgl_ResizeContext(struct GLContextIFace *Self, GLsizei width, GLsizei height) { GLcontext context = GET_INSTANCE(Self); GLboolean fullScreen = context->fullScreen; GLboolean relock = GL_FALSE; if (context->w3dLocked == GL_TRUE) { switch(context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: smartlock_forceUnlock(context->smartLock); break; case MGL_LOCK_MANUAL: IWarp3D->W3D_UnLockHardware(context->w3dContext); relock = GL_TRUE; context->w3dLocked = GL_FALSE; break; } } vid_CloseCurrentDisplay(context); if (fullScreen) { vid_OpenDisplay(context, (int)width, (int)height, MGL_SM_BESTMODE); } else { vid_OpenWindow(context, width, height, 30, 30); } /* Create the Warp3D context if necessary */ if (!context->w3dContext) { if (!vid_CreateWarp3DContext(context)) { vid_CloseCurrentDisplay(context); return; } /* Allocate stencil buffer and depth buffer if necessary */ if (!vid_AllocDepthStencil(context, GL_FALSE)) { vid_DestroyWarp3DContext(context); vid_CloseCurrentDisplay(context); return; } vid_SetDefaultStates(context); } context->w3dChipID = context->w3dContext->CurrentChip; RebindTextures(context); if (relock == GL_TRUE) { switch(context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: smartlock_beginDraw(context->smartLock); smartlock_endDraw(context->smartLock); break; case MGL_LOCK_MANUAL: IWarp3D->W3D_LockHardware(context->w3dContext); break; } context->w3dLocked = GL_TRUE; } } GLboolean cgl_SetDisplayMode(struct GLContextIFace *Self, GLboolean windowed, GLsizei width, GLsizei height, GLint depth) { GLcontext context = GET_INSTANCE(Self); GLboolean relock = GL_FALSE; GLboolean success = GL_TRUE; /* Screen mode changes require a complete shutdown/reopen sequence. However * for window size changes, we simply need to re-create the back buffers * and re-allocate depth and stencil buffer */ if (context->windowed && windowed) { if (context->w3dLocked == GL_TRUE) { switch(context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: smartlock_forceUnlock(context->smartLock); break; case MGL_LOCK_MANUAL: IWarp3D->W3D_UnLockHardware(context->w3dContext); relock = GL_TRUE; context->w3dLocked = GL_FALSE; break; } } buf_FreeBuffer(context, &context->currentFrontBuffer); buf_FreeBuffer(context, &context->currentBackBuffer); if ( !buf_AllocBuffer(context, &context->currentFrontBuffer, width, height, context->w3dWindow->RPort->BitMap) ) { success = GL_FALSE; goto done; } if (context->NumBuffers > 1) { if ( !buf_AllocBuffer(context, &context->currentBackBuffer, width, height, context->w3dWindow->RPort->BitMap) ) { success = GL_FALSE; goto done; } } IWarp3D->W3D_FreeZBuffer(context->w3dContext); IWarp3D->W3D_FreeStencilBuffer(context->w3dContext); IWarp3D->W3D_SetDrawRegion( context->w3dContext, context->drawBuffer->bitMap, 0, &(context->w3dScissor) ); success = vid_AllocDepthStencil(context, GL_FALSE); } else { int32 idcmpFlags = 0; if (context->w3dWindow) { IIntuition->GetWindowAttr(context->w3dWindow, WA_IDCMP, &idcmpFlags, sizeof(idcmpFlags)); } vid_CloseCurrentDisplay(context); if (windowed) { context->windowed = GL_TRUE; context->fullScreen = GL_FALSE; } else { context->windowed = GL_FALSE; context->fullScreen = GL_TRUE; } cgl_ResizeContext(Self, width, height); if (context->w3dWindow) { IIntuition->ModifyIDCMP(context->w3dWindow, idcmpFlags); } } done: if (relock == GL_TRUE) { switch(context->LockMode) { case MGL_LOCK_AUTOMATIC: break; case MGL_LOCK_SMART: smartlock_beginDraw(context->smartLock); smartlock_endDraw(context->smartLock); break; case MGL_LOCK_MANUAL: IWarp3D->W3D_LockHardware(context->w3dContext); break; } context->w3dLocked = GL_TRUE; } return success; }