/* * $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 "smartlock.h" #include "sysinc.h" #include #include #include #include #include "util.h" #include "mgl_profileitems.h" extern void vid_MaybeBlitFrontBuffer(GLcontext); void buf_InternalDrawBuffer(GLcontext context, GLenum mode); void buf_InternalReadBuffer(GLcontext context, GLenum mode); GLboolean buf_AllocBuffer(GLcontext context, GLbuffer *buffer, int width, int height, struct BitMap *friend); void buf_FreeBuffer(GLcontext context, GLbuffer *buffer); void cgl_GLDrawBuffer(struct GLContextIFace *Self, GLenum mode) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(DrawBuffer(Self, mode)); buf_InternalDrawBuffer(context, mode); } void buf_InternalDrawBuffer(GLcontext context, GLenum mode) { 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; } } switch (mode) { /* Can't support those ATM. FIXME: Investigate */ case GL_NONE: case GL_FRONT_AND_BACK: context->CurrentError = GL_INVALID_OPERATION; return; case GL_FRONT: case GL_FRONT_RIGHT: case GL_FRONT_LEFT: context->color_buffer.DrawBuffer = GL_FRONT; context->drawBuffer = &context->currentFrontBuffer; break; case GL_BACK: case GL_BACK_RIGHT: case GL_BACK_LEFT: GLFlagError(context, context->currentBackBuffer.bitMap == 0, GL_INVALID_OPERATION); context->color_buffer.DrawBuffer = GL_BACK; context->drawBuffer = &context->currentBackBuffer; break; } /* Handle AUX buffers */ if (mode >= GL_AUX0 && mode <= (GL_AUX0 + MGL_MAX_AUX_BUFFERS - 1)) { uint32 buf = mode - GL_AUX0; if (context->currentAuxBuffer[buf].bitMap == 0) { context->CurrentError = GL_INVALID_OPERATION; return; } context->color_buffer.DrawBuffer = mode; context->drawBuffer = &context->currentAuxBuffer[buf]; } IWarp3D->W3D_SetDrawRegion( context->w3dContext, context->drawBuffer->bitMap, 0, &(context->w3dScissor) ); 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); context->w3dLocked = GL_TRUE; break; } } } void cgl_GLReadBuffer(struct GLContextIFace *Self, GLenum mode) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(ReadBuffer(Self, mode)); buf_InternalReadBuffer(context, mode); } void buf_InternalReadBuffer(GLcontext context, GLenum mode) { switch (mode) { case GL_NONE: case GL_FRONT_AND_BACK: context->CurrentError = GL_INVALID_OPERATION; return; case GL_FRONT: case GL_FRONT_RIGHT: case GL_FRONT_LEFT: context->color_buffer.ReadBuffer = GL_FRONT; context->readBuffer = &context->currentFrontBuffer; break; case GL_BACK: case GL_BACK_RIGHT: case GL_BACK_LEFT: GLFlagError(context, context->currentBackBuffer.bitMap == 0, GL_INVALID_OPERATION); context->color_buffer.ReadBuffer = GL_BACK; context->readBuffer = &context->currentBackBuffer; break; } /* Handle AUX buffers */ if (mode >= GL_AUX0 && mode <= (GL_AUX0 + MGL_MAX_AUX_BUFFERS - 1)) { uint32 buf = mode - GL_AUX0; if (context->currentAuxBuffer[buf].bitMap == 0) { context->CurrentError = GL_INVALID_OPERATION; return; } context->color_buffer.ReadBuffer = mode; context->readBuffer = &context->currentAuxBuffer[buf]; } } void buf_SetFrontBuffer(GLcontext context, void *bitmap, GLboolean free) { context->currentFrontBuffer.bitMap = bitmap; context->currentFrontBuffer.width = IP96->p96GetBitMapAttr(bitmap, P96BMA_WIDTH); context->currentFrontBuffer.height = IP96->p96GetBitMapAttr(bitmap, P96BMA_HEIGHT); context->currentFrontBuffer.rastPort.BitMap = bitmap; if (free) { context->currentFrontBuffer.flags |= BUF_FREE_BITMAP; } else { context->currentFrontBuffer.flags &= ~BUF_FREE_BITMAP; } buf_InternalDrawBuffer(context, context->color_buffer.DrawBuffer); buf_InternalReadBuffer(context, context->color_buffer.ReadBuffer); } void buf_SetBackBuffer(GLcontext context, void *bitmap, GLboolean free) { context->currentBackBuffer.bitMap = bitmap; context->currentBackBuffer.width = IP96->p96GetBitMapAttr(bitmap, P96BMA_WIDTH); context->currentBackBuffer.height = IP96->p96GetBitMapAttr(bitmap, P96BMA_HEIGHT); context->currentBackBuffer.rastPort.BitMap = bitmap; if (free) { context->currentBackBuffer.flags |= BUF_FREE_BITMAP; } else { context->currentBackBuffer.flags &= ~BUF_FREE_BITMAP; } buf_InternalDrawBuffer(context, context->color_buffer.DrawBuffer); buf_InternalReadBuffer(context, context->color_buffer.ReadBuffer); } GLboolean buf_SetAuxBuffer(GLcontext context, GLenum buffer, void *bitmap, GLboolean free) { int bufnum = buffer - GL_AUX0; if (bufnum < 0 || bufnum > MGL_MAX_AUX_BUFFERS) { return GL_FALSE; } context->currentAuxBuffer[bufnum].bitMap = bitmap; context->currentAuxBuffer[bufnum].width = IP96->p96GetBitMapAttr(bitmap, P96BMA_WIDTH); context->currentAuxBuffer[bufnum].height = IP96->p96GetBitMapAttr(bitmap, P96BMA_HEIGHT); if (free) { context->currentAuxBuffer[bufnum].flags |= BUF_FREE_BITMAP; } else { context->currentAuxBuffer[bufnum].flags &= ~BUF_FREE_BITMAP; } buf_InternalDrawBuffer(context, context->color_buffer.DrawBuffer); buf_InternalReadBuffer(context, context->color_buffer.ReadBuffer); return GL_TRUE; } void cgl_MGLSetFrontBuffer(struct GLContextIFace *Self, void *bitmap) { GLcontext context = GET_INSTANCE(Self); // Free the old buffer if there was an internal one buf_FreeBuffer(context, &context->currentFrontBuffer); buf_SetFrontBuffer(context, bitmap, GL_FALSE); } void cgl_MGLSetBackBuffer(struct GLContextIFace *Self, void *bitmap) { GLcontext context = GET_INSTANCE(Self); // Free the old buffer if there was an internal one buf_FreeBuffer(context, &context->currentBackBuffer); buf_SetBackBuffer(context, bitmap, GL_FALSE); } GLboolean cgl_MGLSetAuxBuffer(struct GLContextIFace *Self, GLenum buffer, void *bitmap) { GLcontext context = GET_INSTANCE(Self); /* FIXME: Free current buffer ? */ GLboolean res = buf_SetAuxBuffer(context, buffer, bitmap, GL_TRUE); if (res) { buf_InternalDrawBuffer(context, context->color_buffer.DrawBuffer); } return res; } void buf_InitBuffer(GLcontext context, GLbuffer *buffer) { buffer->bitMap = 0; buffer->width = 0; buffer->height = 0; buffer->flags = 0; IGraphics->InitRastPort(&buffer->rastPort); } GLboolean buf_AllocBuffer(GLcontext context, GLbuffer *buffer, int width, int height, struct BitMap *friend) { struct BitMap *bitMap = IGraphics->AllocBitMap( width, height, 8, BMF_MINPLANES|BMF_DISPLAYABLE, friend ); if (!bitMap) { return GL_FALSE; } buffer->bitMap = bitMap; buffer->width = width; buffer->height = height; buffer->flags |= BUF_FREE_BITMAP; buffer->rastPort.BitMap = buffer->bitMap; return GL_TRUE; } void buf_FreeBuffer(GLcontext context, GLbuffer *buffer) { if (!buffer->bitMap) { return; } if (buffer->flags & BUF_FREE_BITMAP) { IGraphics->FreeBitMap(buffer->bitMap); buffer->bitMap = 0; buffer->flags &= ~BUF_FREE_BITMAP; } } GLsizei buf_GetBufferHeight(GLcontext context, GLbuffer *buffer) { return buffer->height; } void cgl_GLFinish(struct GLContextIFace *Self) { GLcontext context = GET_INSTANCE(Self); PROFILE_ENTRY(FID_CGL_GL_FINISH); Self->GLFlush(); IWarp3D->W3D_WaitIdle(context->w3dContext); PROFILE_EXIT(FID_CGL_GL_FINISH); } void cgl_GLFlush(struct GLContextIFace *Self) { GLcontext context = GET_INSTANCE(Self); PROFILE_ENTRY(FID_CGL_GL_FLUSH); Self->UnlockDisplay(); //if (context->windowed) vid_MaybeBlitFrontBuffer(context); PROFILE_EXIT(FID_CGL_GL_FLUSH); } /* Loosely analageous to glXWaitGL() */ void cgl_WaitGL(struct GLContextIFace *Self) { GLcontext context = GET_INSTANCE(Self); IWarp3D->W3D_WaitIdle(context->w3dContext); }