deargui-vpl/ref/virtools/Samples/Behaviors/Shader/Sources/StretchRect.cpp

189 lines
6.3 KiB
C++

/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
//
// 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;
}