///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // // StretchRect // ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// #include "stdafx.h" #include "CKRasterizer.h" CKERROR CreateStretchRectProto(CKBehaviorPrototype **); int StretchRect(const CKBehaviorContext& behcontext); extern CKGUID CKPGUID_CUBEFACE; // input parameters enum { InParam_SrcTexture = 0, InParam_SrcRect, InParam_SrcCubeFace, InParam_DestTexture, InParam_DestRect, InParam_DestCubeFace, InParam_Filtered }; CKObjectDeclaration *FillBehaviorStretchRect() { CKObjectDeclaration *od = CreateCKObjectDeclaration("Stretch Rect"); od->SetDescription("copy a rectangular area of the framebuffer into a texture, with possible stretching"); od->SetCategory("Shaders/General"); od->SetType(CKDLL_BEHAVIORPROTOTYPE); od->SetGuid(CKGUID(0x3f1c662a, 0x167e6d7f)); od->SetAuthorGuid(CKGUID()); od->SetAuthorName("Virtools"); od->SetVersion(0x00010000); od->SetCreationFunction(CreateStretchRectProto); return od; } CKERROR CreateStretchRectProto(CKBehaviorPrototype **pproto) { CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("Stretch Rect"); if(!proto) return CKERR_OUTOFMEMORY; proto->DeclareInput("In"); proto->DeclareOutput("Out"); proto->DeclareOutput("Error"); proto->DeclareInParameter("Source Texture", CKPGUID_TEXTURE); proto->DeclareInParameter("Source Rect", CKPGUID_RECT, "(0,0),(0,0)" ); proto->DeclareInParameter("Source Cube Face", CKPGUID_CUBEFACE, "XPos" ); proto->DeclareInParameter("Dest Texture", CKPGUID_TEXTURE); proto->DeclareInParameter("Dest Rect", CKPGUID_RECT, "(0,0),(0,0)" ); proto->DeclareInParameter("Dest Cube Face", CKPGUID_CUBEFACE, "XPos" ); proto->DeclareInParameter("Filtered", CKPGUID_BOOL, "TRUE" ); proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL); proto->SetFunction(StretchRect); proto->SetBehaviorFlags(CKBEHAVIOR_TARGETABLE); *pproto = proto; return CK_OK; } static int SetupCKTextureRstID(const CKBehaviorContext& behcontext, int inputParameter) { CKBehavior* beh = behcontext.Behavior; CKDWORD rstTexID = 0; CK_ID texObjectID; if (beh->GetInputParameterValue(inputParameter, &texObjectID) == CK_OK) { CKTexture* destTex = (CKTexture*) behcontext.Context->GetObject(texObjectID); if (destTex) { destTex->EnsureVideoMemory(behcontext.CurrentRenderContext); rstTexID = destTex->GetRstTextureIndex(); } } return rstTexID; } static CKRECT* vxRectToCKRECT(const VxRect* src, CKRECT& destStorage) { if (!src) return NULL; destStorage.bottom = (int) src->bottom; destStorage.top = (int) src->top; destStorage.left = (int) src->left; destStorage.right = (int) src->right; return &destStorage; } int StretchRect(const CKBehaviorContext& behcontext) { CKBehavior* beh = behcontext.Behavior; beh->ActivateInput(0,FALSE); // CKRasterizerContext* rsctx = behcontext.CurrentRenderContext->GetRasterizerContext(); if (!rsctx) { beh->ActivateOutput(1); return CKBR_OK; } // VxRect fSrcRect; VxRect fDestRect; CKRECT srcRect; CKRECT destRect; VxRect* fSrcRectPtr = NULL; VxRect* fDestRectPtr = NULL; int srcTexID = SetupCKTextureRstID(behcontext, InParam_SrcTexture); int destTexID = SetupCKTextureRstID(behcontext, InParam_DestTexture); if (beh->GetInputParameterValue(InParam_SrcRect, &fSrcRect) == CK_OK) { fSrcRectPtr = fSrcRect.IsNull() ? NULL : &fSrcRect; } if (beh->GetInputParameterValue(InParam_DestRect, &fDestRect) == CK_OK) { fDestRectPtr = fDestRect.IsNull() ? NULL : &fDestRect; } CKBOOL filter = TRUE; beh->GetInputParameterValue(InParam_Filtered, &filter); // CKDWORD srcCubeFace = CKRST_CUBEFACE_XPOS; CKDWORD destCubeFace = CKRST_CUBEFACE_XPOS; // beh->GetInputParameterValue(InParam_SrcCubeFace, &srcCubeFace); beh->GetInputParameterValue(InParam_DestCubeFace, &destCubeFace); // CKRST_STRETCHRECT_ERROR srErr = (rsctx->StretchRect(destTexID, vxRectToCKRECT(fDestRectPtr, destRect), (CKRST_CUBEFACE) destCubeFace, srcTexID, vxRectToCKRECT(fSrcRectPtr, srcRect), (CKRST_CUBEFACE) srcCubeFace, filter)); if (srErr != CKRST_STRETCHRECT_NO_ERROR) { char* errMsg; switch(srErr) { case CKRST_STRETCHRECT_UNSUPPORTED: errMsg = "Stretch Rect : Rasterizer has no stretch rect support."; break; case CKRST_STRETCHRECT_DEST_EQUAL_SOURCE_ERROR: errMsg = "Stretch Rect : Source and Destination should be different."; break; case CKRST_STRETCHRECT_BLIT_FROM_MULTISAMPLED_BACKBUFFER_ERROR: errMsg = "Stretch Rect : Can't stretch rect from a multisampled render target. \n" "You should use the 'Resolve Multisampling' BB prior ro 'Stetch Rect'. \n" "You should also activate the 'CK2_3D/OffscreenMultiSampledBuffer' in order to permit such manual multisampling resolve."; break; case CKRST_STRETCHRECT_BLIT_TO_MULTISAMPLED_BACKBUFFER_ERROR: errMsg = "Stretch Rect : Can't stretch rect to a multisampled render target. \n" "You should use the 'Resolve Multisampling' BB prior ro 'Stetch Rect'. \n" "You should also activate the 'CK2_3D/OffscreenMultiSampledBuffer' in order to permit such manual multisampling resolve."; break; case CKRST_STRETCHRECT_NONPOW2_SRC_TEX_ERROR: errMsg = "Stretch Rect : Source texture dimensions should be powers of 2, unless the source is the back buffer."; break; case CKRST_STRETCHRECT_NONPOW2_DEST_TEX_ERROR: errMsg = "Stretch Rect : Destination texture dimensions should be powers of 2, unless the destination is the back buffer."; break; case CKRST_STRETCHRECT_SRC_RECT_ERROR: errMsg = "Stretch Rect : Source rectangle is outside of the surface."; break; case CKRST_STRETCHRECT_DEST_RECT_ERROR: errMsg = "Stretch Rect : Dest rectangle is outside of the surface."; break; case CKRST_STRETCHRECT_BAD_CUBE_FACE_ERROR: errMsg = "Stretch Rect : Cube map face is invalid."; break; break; default: case CKRST_STRETCHRECT_OPERATION_FAILED_ERROR: errMsg = "Stretch Rect : Stretch rect operation failed (possibly due to unsupportedd multisampling / format / texture type combination."; break; break; } beh->m_Context->OutputToConsole(errMsg); beh->ActivateOutput(1); return CKBR_OK; } beh->ActivateOutput(0); return CKBR_OK; }