📄 drawprim.c
字号:
/******************************************************************************
<module>
* Name : DrawPrim.c
* Title : D3DM DrawPrimitives Callback
* Author(s) : Imagination Technologies
* Created : 2 March 2004
*
* Copyright : 2004 by Imagination Technologies Limited.
* All rights reserved. No part of this software, either
* material or conceptual may be copied or distributed,
* transmitted, transcribed, stored in a retrieval system
* or translated into any human or computer language in any
* form by any means, electronic, mechanical, manual or
* other-wise, or disclosed to third parties without the
* express written permission of Imagination Technologies
* Limited, Unit 8, HomePark Industrial Estate,
* King's Langley, Hertfordshire, WD4 8LZ, U.K.
*
* Description : DrawPrimitive Entry Point for processing D3DMobile DP Commands,
* and DP Operation Handlers
*
* Platform : Windows CE
*
</module>
********************************************************************************/
#include "context.h"
void Clear( LPD3DM_CONTEXT psContext,
DWORD dwFlags,
DWORD dwFillColour,
float fFillDepth,
DWORD dwNumRects,
LPD3DMRECT psRects);
void SetViewPort(LPD3DM_CONTEXT psContext, LPD3DMRECT psRect);
/*----------------------------------------------------------------------------
<function>
FUNCTION: D3DM_DP_OP_DefaultHandler
PURPOSE:
PARAMETERS: In: psContext - Context to operate on
In: pvCommandData - Pointer to command ops to execute
In: nCount - number of ops of this type to process
RETURNS: number of bytes processed
</function>
------------------------------------------------------------------------------*/
ULONG D3DM_DP_OP_DefaultHandler(LPD3DM_CONTEXT psContext, LPVOID pvCommandData, WORD nCount)
{
D3DM_DPF((DPF_ERROR, "D3DM_DP_OP_DefaultHandler: Unsupported operation requested"));
return 0;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: D3DM_DP_OP_BeginScene
PURPOSE:
PARAMETERS: In: psContext - Context to operate on
In: pvCommandData - Pointer to command ops to execute
In: nCount - number of ops of this type to process
RETURNS: number of bytes processed
</function>
------------------------------------------------------------------------------*/
ULONG D3DM_DP_OP_BeginScene(LPD3DM_CONTEXT psContext, LPVOID pvCommandData, WORD nCount)
{
D3DM_DPF((DPF_ENTRY, "->D3DM_DP_OP_BeginScene"));
// Can't trust Begin/EndScene Ops
// just ignore and infer:
// beginscene from first primitive/clear
// endscene from present or setrendertarget
D3DM_DPF((DPF_EXIT, "<-D3DM_DP_OP_BeginScene"));
return 0;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: D3DM_DP_OP_EndScene
PURPOSE:
PARAMETERS: In: psContext - Context to operate on
In: pvCommandData - Pointer to command ops to execute
In: nCount - number of ops of this type to process
RETURNS: number of bytes processed
</function>
------------------------------------------------------------------------------*/
ULONG D3DM_DP_OP_EndScene(LPD3DM_CONTEXT psContext, LPVOID pvCommandData, WORD nCount)
{
D3DM_DPF((DPF_ENTRY, "->D3DM_DP_OP_EndScene"));
// Can't trust Begin/EndScene Ops
// just ignore and infer:
// beginscene from first primitive/clear
// endscene from present or setrendertarget
D3DM_DPF((DPF_EXIT, "<-D3DM_DP_OP_EndScene"));
return 0;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: D3DM_DP_OP_Present
PURPOSE:
PARAMETERS: In: psContext - Context to operate on
In: pvCommandData - Pointer to command ops to execute
In: nCount - number of ops of this type to process
RETURNS: number of bytes processed
</function>
------------------------------------------------------------------------------*/
ULONG D3DM_DP_OP_Present(LPD3DM_CONTEXT psContext, LPVOID pvCommandData, WORD nCount)
{
WORD i;
ULONG ulBytesProcessed;
LPD3DM_PRESENT psCurrentOp;
ulBytesProcessed = 0;
psCurrentOp = (LPD3DM_PRESENT) pvCommandData;
D3DM_DPF((DPF_ENTRY, "->D3DM_DP_OP_CursorProperties"));
/* We infer endscene from Present - always call this to flush any clears */
DoEndScene(psContext);
for(i=0; i <nCount; i++)
{
/* Process current Present */
LPD3DM_SURFACE psSurface = (LPD3DM_SURFACE) psCurrentOp->PresentSurface;
ulBytesProcessed += sizeof(D3DM_PRESENT);
if(psSurface->eSurfaceType != D3DMRTYPE_BACKBUFFER &&
psSurface->eSurfaceType != D3DMRTYPE_FRONTBUFFER)
{
/* Can't present non image surfaces */
D3DM_DPF((DPF_ERROR, "D3DM_DP_OP_Present:Invalid buffer type submitted for Presentation"));
psContext->hrLastError = D3DM_GENERICFAILURE;
return ulBytesProcessed;
}
/* Check Scene validity */
if(IS_RENDER_TARGET(psSurface) && SCENE_IS_INVALID(psSurface))
{
/* Scene is invalidated due to Power management*/
continue;
}
if(psContext->SwapEffect == D3DMSWAPEFFECT_FLIP)
{
PresentFlip(psContext->psCurrentRenderTarget, psContext->nVSyncInterval);
/* advance to next surface */
psContext->sChain.psCurrentBuffer = psContext->sChain.psCurrentBuffer->psNext;
SetRenderTarget(psContext,
psContext->sChain.psCurrentBuffer,
psContext->psCurrentDepthBuffer,
IMG_FALSE);
}
else
{
Copy(psCurrentOp);
}
/* Move past variable length array at end of struct */
ulBytesProcessed += (sizeof(RECT) * psCurrentOp->NumClippingRects);
psCurrentOp = (LPD3DM_PRESENT) ((DWORD)pvCommandData) + ulBytesProcessed;
}
D3DM_DPF((DPF_EXIT, "<-D3DM_DP_OP_CursorProperties"));
return ulBytesProcessed;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: D3DM_DP_OP_CopyRect
PURPOSE:
PARAMETERS: In: psContext - Context to operate on
In: pvCommandData - Pointer to command ops to execute
In: nCount - number of ops of this type to process
RETURNS: number of bytes processed
</function>
------------------------------------------------------------------------------*/
ULONG D3DM_DP_OP_CopyRect(LPD3DM_CONTEXT psContext, LPVOID pvCommandData, WORD nCount)
{
WORD i;
ULONG ulBytesProcessed;
LPD3DM_COPYRECT psCurrentOp;
ulBytesProcessed = 0;
psCurrentOp = (LPD3DM_COPYRECT) pvCommandData;
D3DM_DPF((DPF_ENTRY, "->D3DM_DP_OP_CopyRect"));
for(i=0; i <nCount; i++, psCurrentOp++)
{
/* Process current Copy Rect */
CopyRectangle(psCurrentOp);
ulBytesProcessed += sizeof(D3DM_COPYRECT);
}
D3DM_DPF((DPF_EXIT, "<-D3DM_DP_OP_CopyRect"));
return ulBytesProcessed;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: D3DM_DP_OP_Clear
PURPOSE:
PARAMETERS: In: psContext - Context to operate on
In: pvCommandData - Pointer to command ops to execute
In: nCount - number of ops of this type to process
RETURNS: number of bytes processed
</function>
------------------------------------------------------------------------------*/
ULONG D3DM_DP_OP_Clear(LPD3DM_CONTEXT psContext, LPVOID pvCommandData, WORD nCount)
{
WORD i;
ULONG ulBytesProcessed;
LPD3DM_CLEAR psCurrentOp;
ulBytesProcessed = 0;
psCurrentOp = (LPD3DM_CLEAR) pvCommandData;
D3DM_DPF((DPF_ENTRY, "->D3DM_DP_OP_Clear"));
for(i=0; i <nCount; i++, psCurrentOp++)
{
if (psContext->psCurrentRenderTarget)
{
// FillStencil, no stencils
Clear(psContext,
psCurrentOp->Flags,
psCurrentOp->FillColor,
psCurrentOp->FillDepth,
psCurrentOp->NumRects,
(LPD3DMRECT)&psCurrentOp->Rects);
}
/* Process current operation */
ulBytesProcessed += sizeof(D3DM_CLEAR);
}
D3DM_DPF((DPF_EXIT, "<-D3DM_DP_OP_Clear"));
return ulBytesProcessed;
}
/*****************************************************************************
FUNCTION : SetRenderTarget
PURPOSE : Core code to change render-target
PARAMETERS : psContext - valid D3D context
psSurfData - Valid Surface data for the new render-target
RETURNS : none
*****************************************************************************/
void SetRenderTarget(LPD3DM_CONTEXT psContext,
LPD3DM_SURFACE psNewRenderTarget,
LPD3DM_SURFACE psNewDepthBuffer,
IMG_BOOL bDisallowEndScene)
{
LPD3DM_SURFACE psCurrentRenderTarget;
D3DMRECT sFSRect;
D3DM_DPF((DPF_MESSAGE, "SetRenderTarget: New render-target %#8.8lX", psNewRenderTarget));
/* has RT surface changed? */
if(psContext->psCurrentRenderTarget == psNewRenderTarget)
{
return;
}
/* Validate the new render-target */
if(!IS_RENDER_TARGET(psNewRenderTarget))
{
D3DM_DPF((DPF_ERROR, "SetRenderTarget: surface is not a render target, failing" ));
return;
}
/*
Do we have something started on the current render surface?
If so we'd better sort it out...
*/
psCurrentRenderTarget = psContext->psCurrentRenderTarget;
if(psCurrentRenderTarget)
{
/*
To handle mid-scene texture renders:
When switching away from a non-texture render-target (i.e.
probably the render-target for the whole scene) to a texture,
we save the current HW-context so that the scene can be
continued later when we switch back.
When switching away from a texture (either to another texture
or to a non-texture) we always render the scene. Note that
this behaviour assumes that applications do not perform sub-
renders within mid-scene texture-renders, or render their
textures incrementally throughout the main scene! - wouldn't
that be nice.
*/
if(!bDisallowEndScene &&
(psCurrentRenderTarget->eSurfaceType == D3DMRTYPE_TEXTURE ||
psCurrentRenderTarget->eSurfaceType == D3DMRTYPE_SURFACE))
{
/*
Switching from a texture, or to a non texture, or to
something with the same dimensions -- so render the scene.
*/
D3DM_DPF((DPF_MESSAGE, "SetRenderTarget: ending scene (render needed) on surface 0x%8.8lX", psCurrentRenderTarget ));
DoEndScene(psContext);
}
}
/* Record that the new render-target surface and depth buffer are being used by this context */
psContext->psCurrentRenderTarget = psNewRenderTarget;
psContext->psCurrentDepthBuffer = psNewDepthBuffer;
/* Associate depth buffer with render target */
psNewRenderTarget->sDescription.sSurface.psAssocDepthSurface = psNewDepthBuffer;
/* Check if we need to force a Z-Buffer meminfo creation */
if(psNewDepthBuffer && (psNewDepthBuffer->dwFlags & D3DM_SURFACE_FLAGS_CREATE_Z_BUFFER))
{
/* Create Z buffer */
ZLSAlloc(psContext);
psNewDepthBuffer->dwFlags &= ~D3DM_SURFACE_FLAGS_CREATE_Z_BUFFER;
}
/*
Size of render surface has changed so need
to recalc TA region clip for FS.
*/
VLSetRect(&sFSRect,
0,
0,
psNewRenderTarget->dwWidth - 1,
psNewRenderTarget->dwHeight - 1);
psNewRenderTarget->sDescription.sSurface.dwFSRegionClip = CalcTARegionClip(psContext, &sFSRect);
/*
Render surface can't be twiddled.
May cause problems if already blit to
*/
if(psNewRenderTarget->eSurfaceType == D3DMRTYPE_TEXTURE &&
psNewRenderTarget->dwFlags & D3DM_SURFACE_FLAGS_TWIDDLED)
{
/* We cant render to a twiddled surface */
UnTwiddleSurface(psNewRenderTarget);
}
/* Readjust our vp transform */
SetupViewportTransform(psContext);
/*
Update all the TA and 3D-core registers that relate to the
render-target
*/
SetupRenderTargetRegs(psContext);
/* resubmit the HW state */
ResubmitHWState(psContext);
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: D3DM_DP_OP_RenderTarget
PURPOSE:
PARAMETERS: In: psContext - Context to operate on
In: pvCommandData - Pointer to command ops to execute
In: nCount - number of ops of this type to process
RETURNS: number of bytes processed
</function>
------------------------------------------------------------------------------*/
ULONG D3DM_DP_OP_RenderTarget(LPD3DM_CONTEXT psContext, LPVOID pvCommandData, WORD nCount)
{
WORD i;
ULONG ulBytesProcessed;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -