Michael Gopshtein
Michael Gopshtein

Reputation: 350

Chaining Direct2D Effects

I have created a simple Direct2D Effect, which flips the incoming image (can flip either horizontally or vertically or both at the same time). The custom effect seems to work fine. The problem starts when I try to chain two instances of the effect one after another:

ID2D1Effect *flip1;  // initialized
ID2D1Effect *flip2;  // initialized
ID2D1Bitmap1 *bmp;   // initialized
flip1->SetInput(0, bmp);
flip2->SetInputEffect(0, flip1);

// ...
ID2D1DeviceContext *pContext; // initialized
pContext->BeginDraw();
pContext->DrawImage(flip2);
pContext->EndDraw();

As result I'm sometimes getting a "junk" image as the output. I noticed that as long as the second flip configured to leave the image as is, this chain works file. When the second flip modifies the image, I get whole or part of the target image "garbaged".

My suspicion is that, as the flip effect uses a complex sampling (target color of pixel xy depends on original pixel at different location), somehow the second flip effect tries to access an output pixel of the first flip, which is not ready yet.

Does this assumption make sense? Is there a way to avoid it? I always have a fallback of rendering each effect on a different target Bitmap, but I assumed this will take longer time than simply chaining the effects together.

Upvotes: 1

Views: 362

Answers (1)

Sempai-Dami1
Sempai-Dami1

Reputation: 11

The problem may be due to static data in your code or matrix transform issue. The static data in class functions are global to the objects.

class foo
{

public:

static int cls_counter;

foo()
{

 static int func_counter;

 int obj_counter = 0;

 // some code that affects the three variables
 ++cls_counter;
 ++func_counter;
 ++obj_counter;

}

};

int foo::clss_counter = 0;

foo fighter1; // obj_counter last value 1, foo::foo::func_counter = 1, foo::cls_counter = 1
foo fighter2; // obj_counter last value 1, foo::foo::func_counter = 2, foo::cls_counter = 2
foo fighter3; // obj_counter last value 1, foo::foo::func_counter = 3, foo::cls_counter = 3

if that fails go back to the drawing board for now, compare your custom effect's internal logic and result to this code.

dvctxt->BeginDraw();

// clear any previous errors
dvctxt->Flush();

// always reset to the bgnd buffer
dvctxt->SetTarget(hwnd_bgnd_bmp1);

// optional
dvctxt->Clear(bgnd_colr);

// optional
dvctxt->DrawBitmap(bgnd_bmp1);

// always default to the identity matrix or a preferred matrix before drawing
D2D1_MATRIX_3x2_F final_mtrx = D2D1::Matrix3x2F::Identity();

float hsize = 1.0f;
float vsize = 1.0f;

if (flag_hflip || flag_vflip)
{     
    if (flag_hflip) { hsize = -1.0f; }
    if (flag_vflip) { vsize = -1.0f; }

    D2D1_POINT_2F scale_pt = { 0.0f };

    final_mtrx = D2D1::Martix3x2F::Scale(hsize, vsize, scale_pt);
}

dvctxt->SetTransform(&final_mtrx);

dvctxt->DrawImage(src_image);

// draw overlays

dvctxt->EndDraw();

// external BeginDraw()...EndDraw() overlays

swp_chain->Present(0,0);

Upvotes: 0

Related Questions