1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ExtendInputEffectD2D1.h"
11 #include "ShadersD2D1.h"
12 #include "HelpersD2D.h"
18 TEXTW(#X) // This macro creates a single string from multiple lines of text.
20 static const PCWSTR kXmlDescription
=
24 <!-- System Properties
-->
25 <Property name
='DisplayName' type
='string' value
='ExtendInputEffect'/>
26 <Property name
='Author' type
='string' value
='Mozilla'/>
27 <Property name
='Category' type
='string' value
='Utility Effects'/>
28 <Property name
='Description' type
='string' value
='This effect is used to extend the output rect of any input effect to a specified rect.'/>
30 <Input name
='InputEffect'/>
32 <Property name
='OutputRect' type
='vector4'>
33 <Property name
='DisplayName' type
='string' value
='Output Rect'/>
41 ExtendInputEffectD2D1::ExtendInputEffectD2D1()
43 mOutputRect(D2D1::Vector4F(-FLT_MAX
, -FLT_MAX
, FLT_MAX
, FLT_MAX
)) {}
46 ExtendInputEffectD2D1::Initialize(ID2D1EffectContext
* pContextInternal
,
47 ID2D1TransformGraph
* pTransformGraph
) {
49 hr
= pTransformGraph
->SetSingleTransformNode(this);
59 ExtendInputEffectD2D1::PrepareForRender(D2D1_CHANGE_TYPE changeType
) {
64 ExtendInputEffectD2D1::SetGraph(ID2D1TransformGraph
* pGraph
) {
68 IFACEMETHODIMP_(ULONG
)
69 ExtendInputEffectD2D1::AddRef() { return ++mRefCount
; }
71 IFACEMETHODIMP_(ULONG
)
72 ExtendInputEffectD2D1::Release() {
81 ExtendInputEffectD2D1::QueryInterface(const IID
& aIID
, void** aPtr
) {
86 if (aIID
== IID_IUnknown
) {
87 *aPtr
= static_cast<IUnknown
*>(static_cast<ID2D1EffectImpl
*>(this));
88 } else if (aIID
== IID_ID2D1EffectImpl
) {
89 *aPtr
= static_cast<ID2D1EffectImpl
*>(this);
90 } else if (aIID
== IID_ID2D1DrawTransform
) {
91 *aPtr
= static_cast<ID2D1DrawTransform
*>(this);
92 } else if (aIID
== IID_ID2D1Transform
) {
93 *aPtr
= static_cast<ID2D1Transform
*>(this);
94 } else if (aIID
== IID_ID2D1TransformNode
) {
95 *aPtr
= static_cast<ID2D1TransformNode
*>(this);
100 static_cast<IUnknown
*>(*aPtr
)->AddRef();
104 static D2D1_RECT_L
ConvertFloatToLongRect(const D2D1_VECTOR_4F
& aRect
) {
105 // Clamp values to LONG range. We can't use std::min/max here because we want
106 // the comparison to operate on a type that's different from the type of the
108 return D2D1::RectL(aRect
.x
<= float(LONG_MIN
) ? LONG_MIN
: LONG(aRect
.x
),
109 aRect
.y
<= float(LONG_MIN
) ? LONG_MIN
: LONG(aRect
.y
),
110 aRect
.z
>= float(LONG_MAX
) ? LONG_MAX
: LONG(aRect
.z
),
111 aRect
.w
>= float(LONG_MAX
) ? LONG_MAX
: LONG(aRect
.w
));
114 static D2D1_RECT_L
IntersectRect(const D2D1_RECT_L
& aRect1
,
115 const D2D1_RECT_L
& aRect2
) {
116 return D2D1::RectL(std::max(aRect1
.left
, aRect2
.left
),
117 std::max(aRect1
.top
, aRect2
.top
),
118 std::min(aRect1
.right
, aRect2
.right
),
119 std::min(aRect1
.bottom
, aRect2
.bottom
));
123 ExtendInputEffectD2D1::MapInputRectsToOutputRect(
124 const D2D1_RECT_L
* pInputRects
, const D2D1_RECT_L
* pInputOpaqueSubRects
,
125 UINT32 inputRectCount
, D2D1_RECT_L
* pOutputRect
,
126 D2D1_RECT_L
* pOutputOpaqueSubRect
) {
127 // This transform only accepts one input, so there will only be one input
129 if (inputRectCount
!= 1) {
133 // Set the output rect to the specified rect. This is the whole purpose of
135 *pOutputRect
= ConvertFloatToLongRect(mOutputRect
);
136 *pOutputOpaqueSubRect
= IntersectRect(*pOutputRect
, pInputOpaqueSubRects
[0]);
141 ExtendInputEffectD2D1::MapOutputRectToInputRects(const D2D1_RECT_L
* pOutputRect
,
142 D2D1_RECT_L
* pInputRects
,
143 UINT32 inputRectCount
) const {
144 if (inputRectCount
!= 1) {
148 *pInputRects
= *pOutputRect
;
153 ExtendInputEffectD2D1::MapInvalidRect(UINT32 inputIndex
,
154 D2D1_RECT_L invalidInputRect
,
155 D2D1_RECT_L
* pInvalidOutputRect
) const {
156 MOZ_ASSERT(inputIndex
== 0);
158 *pInvalidOutputRect
= invalidInputRect
;
163 ExtendInputEffectD2D1::Register(ID2D1Factory1
* aFactory
) {
164 D2D1_PROPERTY_BINDING bindings
[] = {
165 D2D1_VALUE_TYPE_BINDING(L
"OutputRect",
166 &ExtendInputEffectD2D1::SetOutputRect
,
167 &ExtendInputEffectD2D1::GetOutputRect
),
169 HRESULT hr
= aFactory
->RegisterEffectFromString(
170 CLSID_ExtendInputEffect
, kXmlDescription
, bindings
, 1, CreateEffect
);
173 gfxWarning() << "Failed to register extend input effect.";
178 void ExtendInputEffectD2D1::Unregister(ID2D1Factory1
* aFactory
) {
179 aFactory
->UnregisterEffect(CLSID_ExtendInputEffect
);
182 HRESULT __stdcall
ExtendInputEffectD2D1::CreateEffect(IUnknown
** aEffectImpl
) {
183 *aEffectImpl
= static_cast<ID2D1EffectImpl
*>(new ExtendInputEffectD2D1());
184 (*aEffectImpl
)->AddRef();
190 } // namespace mozilla