/*
 * Copyright 2023 Zhiyi Zhang for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

import "objidl.idl";
import "d2dbasetypes.h";
import "dcommon.idl";
import "dcompanimation.idl";
import "dcomptypes.idl";
import "unknwn.idl";

typedef struct _D3DMATRIX
{
    float m[4][4];
} D3DMATRIX;

[
    local,
    object,
    pointer_default(unique),
    uuid(bb8a4953-2c99-4f5a-96f5-4819027fa3ac)
]
interface IDCompositionSurface : IUnknown
{
    HRESULT BeginDraw([in, optional] const RECT *rect, [in] REFIID iid, [out] void **object, [out] POINT *offset);
    HRESULT EndDraw();
    HRESULT SuspendDraw();
    HRESULT ResumeDraw();
    HRESULT Scroll([in, optional] const RECT *scroll, [in, optional] const RECT *clip, [in] int offset_x, [in] int offset_y);
}

[
    local,
    object,
    pointer_default(unique),
    uuid(ae471c51-5f53-4a24-8d3e-d0c39c30b3f0)
]
interface IDCompositionVirtualSurface : IDCompositionSurface
{
    HRESULT Resize([in] UINT width, [in] UINT height);
    HRESULT Trim([in, optional, size_is(count)] const RECT *rectangles, [in] UINT count);
}

[
    local,
    object,
    pointer_default(unique),
    uuid(e334bc12-3937-4e02-85eb-fcf4eb30d2c8)
]
interface IDCompositionSurfaceFactory : IUnknown
{
    HRESULT CreateSurface([in] UINT width, [in] UINT height, [in] DXGI_FORMAT pixel_format, [in] DXGI_ALPHA_MODE alpha_mode, [out] IDCompositionSurface **surface);
    HRESULT CreateVirtualSurface([in] UINT width, [in] UINT height, [in] DXGI_FORMAT pixel_format, [in] DXGI_ALPHA_MODE alpha_mode, [out] IDCompositionVirtualSurface **surface);
}

[
    local,
    object,
    pointer_default(unique),
    uuid(64ac3703-9d3f-45ec-a109-7cac0e7a13a7)
]
interface IDCompositionClip : IUnknown
{
}

[
    local,
    object,
    pointer_default(unique),
    uuid(9842ad7d-d9cf-4908-aed7-48b51da5e7c2)
]
interface IDCompositionRectangleClip : IDCompositionClip
{
    HRESULT SetLeft([in] float left);
    HRESULT SetLeftAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetTop([in] float top);
    HRESULT SetTopAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetRight([in] float right);
    HRESULT SetRightAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetBottom([in] float bottom);
    HRESULT SetBottomAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetTopLeftRadiusX([in] float radius);
    HRESULT SetTopLeftRadiusXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetTopLeftRadiusY([in] float radius);
    HRESULT SetTopLeftRadiusYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetTopRightRadiusX([in] float radius);
    HRESULT SetTopRightRadiusXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetTopRightRadiusY([in] float radius);
    HRESULT SetTopRightRadiusYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetBottomLeftRadiusX([in] float radius);
    HRESULT SetBottomLeftRadiusXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetBottomLeftRadiusY([in] float radius);
    HRESULT SetBottomLeftRadiusYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetBottomRightRadiusX([in] float radius);
    HRESULT SetBottomRightRadiusXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetBottomRightRadiusY([in] float radius);
    HRESULT SetBottomRightRadiusYAnimation([in] IDCompositionAnimation *animation);
}

[
    local,
    object,
    pointer_default(unique),
    uuid(ec81b08f-bfcb-4e8d-b193-a915587999e8)
]
interface IDCompositionEffect : IUnknown
{
}

[
    local,
    object,
    pointer_default(unique),
    uuid(71185722-246b-41f2-aad1-0443f7f4bfc2)
]
interface IDCompositionTransform3D : IDCompositionEffect
{
}

[
    local,
    object,
    pointer_default(unique),
    uuid(a7929a74-e6b2-4bd6-8b95-4040119ca34d)
]
interface IDCompositionEffectGroup : IDCompositionEffect
{
    HRESULT SetOpacity([in] float opacity);
    HRESULT SetOpacityAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetTransform3D([in, optional] IDCompositionTransform3D *transform);
};

[
    local,
    object,
    pointer_default(unique),
    uuid(91636d4b-9ba1-4532-aaf7-e3344994d788)
]
interface IDCompositionTranslateTransform3D : IDCompositionTransform3D
{
    HRESULT SetOffsetX([in] float offset);
    HRESULT SetOffsetXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetOffsetY([in] float offset);
    HRESULT SetOffsetYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetOffsetZ([in] float offset);
    HRESULT SetOffsetZAnimation([in] IDCompositionAnimation *animation);
};

[
    local,
    object,
    pointer_default(unique),
    uuid(2a9e9ead-364b-4b15-a7c4-a1997f78b389)
]
interface IDCompositionScaleTransform3D : IDCompositionTransform3D
{
    HRESULT SetScaleX([in] float scale);
    HRESULT SetScaleXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetScaleY([in] float scale);
    HRESULT SetScaleYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetScaleZ([in] float scale);
    HRESULT SetScaleZAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterX([in] float center);
    HRESULT SetCenterXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterY([in] float center);
    HRESULT SetCenterYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterZ([in] float center);
    HRESULT SetCenterZAnimation([in] IDCompositionAnimation *animation);
}

[
    local,
    object,
    pointer_default(unique),
    uuid(d8f5b23f-d429-4a91-b55a-d2f45fd75b18)
]
interface IDCompositionRotateTransform3D : IDCompositionTransform3D
{
    HRESULT SetScaleX([in] float scale);
    HRESULT SetScaleXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetScaleY([in] float scale);
    HRESULT SetScaleYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetScaleZ([in] float scale);
    HRESULT SetScaleZAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterX([in] float center);
    HRESULT SetCenterXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterY([in] float center);
    HRESULT SetCenterYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterZ([in] float center);
    HRESULT SetCenterZAnimation([in] IDCompositionAnimation *animation);
}

[
    local,
    object,
    pointer_default(unique),
    uuid(4b3363f0-643b-41b7-b6e0-ccf22d34467c)
]
interface IDCompositionMatrixTransform3D : IDCompositionTransform3D
{
    /* C++ method: HRESULT SetMatrix(const D3DMATRIX &matrix); Use pointer instead of reference */
    HRESULT SetMatrix([in] const D3DMATRIX *matrix);
    HRESULT SetMatrixElement([in] int row, [in] int column, [in] float value);
    HRESULT SetMatrixElementAnimation([in] int row, [in] int column, [in] IDCompositionAnimation *animation);
};

[
    local,
    object,
    pointer_default(unique),
    uuid(fd55faa7-37e0-4c20-95d2-9be45bc33f55)
]
interface IDCompositionTransform : IDCompositionTransform3D
{
}

[
    local,
    object,
    pointer_default(unique),
    uuid(71fde914-40ef-45ef-bd51-68b037c339f9)
]
interface IDCompositionScaleTransform : IDCompositionTransform
{
    HRESULT SetScaleX([in] float scale);
    HRESULT SetScaleXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetScaleY([in] float scale);
    HRESULT SetScaleYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterX([in] float center);
    HRESULT SetCenterXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterY([in] float center);
    HRESULT SetCenterYAnimation([in] IDCompositionAnimation *animation);
};

[
    local,
    object,
    pointer_default(unique),
    uuid(641ed83c-ae96-46c5-90dc-32774cc5c6d5)
]
interface IDCompositionRotateTransform : IDCompositionTransform
{
    HRESULT SetAngle([in] float angle);
    HRESULT SetAngleAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterX([in] float center_x);
    HRESULT SetCenterXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterY([in] float center_y);
    HRESULT SetCenterYAnimation([in] IDCompositionAnimation *animation);
};

[
    local,
    object,
    pointer_default(unique),
    uuid(e57aa735-dcdb-4c72-9c61-0591f58889ee)
]
interface IDCompositionSkewTransform : IDCompositionTransform
{
    HRESULT SetAngleX([in] float angle);
    HRESULT SetAngleXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetAngleY([in] float angle);
    HRESULT SetAngleYAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterX([in] float center);
    HRESULT SetCenterXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetCenterY([in] float center);
    HRESULT SetCenterYAnimation([in] IDCompositionAnimation *animation);
};

[
    local,
    object,
    pointer_default(unique),
    uuid(16cdff07-c503-419c-83f2-0965c7af1fa6)
]
interface IDCompositionMatrixTransform : IDCompositionTransform
{
    /* C++ method: HRESULT SetMatrix(const D2D_MATRIX_3X2_F &matrix); Use pointer instead of reference */
    HRESULT SetMatrix([in] const D2D_MATRIX_3X2_F *matrix);
    HRESULT SetMatrixElement([in] int row, [in] int column, [in] float value);
    HRESULT SetMatrixElementAnimation([in] int row, [in] int column, [in] IDCompositionAnimation *animation);
};

[
    local,
    object,
    pointer_default(unique),
    uuid(06791122-c6f0-417d-8323-269e987f5954)
]
interface IDCompositionTranslateTransform : IDCompositionTransform
{
    HRESULT SetOffsetX([in] float offset);
    HRESULT SetOffsetXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetOffsetY([in] float offset);
    HRESULT SetOffsetYAnimation([in] IDCompositionAnimation *animation);
};

[
    object,
    uuid(4d93059d-097b-4651-9a60-f0f25116e2f3),
    local,
    pointer_default(unique)
]
interface IDCompositionVisual : IUnknown
{
    HRESULT SetOffsetX([in] float offset_x);
    HRESULT SetOffsetXAnimation([in] IDCompositionAnimation *animation);
    HRESULT SetOffsetY([in] float offset_y);
    HRESULT SetOffsetYAnimation([in] IDCompositionAnimation *animation);
    /* C++ method: HRESULT SetTransform(const D2D_MATRIX_3X2_F &matrix); Use pointer instead of reference */
    HRESULT SetTransform([in] const D2D_MATRIX_3X2_F *matrix);
    HRESULT SetTransformObject([in] IDCompositionTransform *transform);
    HRESULT SetTransformParent([in] IDCompositionVisual *visual);
    HRESULT SetEffect([in] IDCompositionEffect *effect);
    HRESULT SetBitmapInterpolationMode([in] enum DCOMPOSITION_BITMAP_INTERPOLATION_MODE interpolation_mode);
    HRESULT SetBorderMode([in] enum DCOMPOSITION_BORDER_MODE border_mode);
    /* C++ method: HRESULT SetClip(const D2D_RECT_F &rect); Use pointer instead of reference */
    HRESULT SetClip([in] const D2D_RECT_F *rect);
    HRESULT SetClipObject([in] IDCompositionClip *clip);
    HRESULT SetContent([in] IUnknown *content);
    HRESULT AddVisual([in] IDCompositionVisual *visual, [in] BOOL insert_above, [in] IDCompositionVisual *reference_visual);
    HRESULT RemoveVisual([in] IDCompositionVisual *visual);
    HRESULT RemoveAllVisuals();
    HRESULT SetCompositeMode([in] enum DCOMPOSITION_COMPOSITE_MODE composite_mode);
}

[
    object,
    uuid(e8de1639-4331-4b26-bc5f-6a321d347a85),
    local,
    pointer_default(unique)
]
interface IDCompositionVisual2 : IDCompositionVisual
{
    HRESULT SetOpacityMode([in] enum DCOMPOSITION_OPACITY_MODE opacity_mode);
    HRESULT SetBackFaceVisibility([in] enum DCOMPOSITION_BACKFACE_VISIBILITY visibility);
}

[
    object,
    uuid(eacdd04c-117e-4e17-88f4-d1b12b0e3d89),
    local,
    pointer_default(unique)
]
interface IDCompositionTarget : IUnknown
{
    HRESULT SetRoot([in] IDCompositionVisual *visual);
}

[
    object,
    uuid(c37ea93a-e7aa-450d-b16f-9746cb0407f3),
    local,
    pointer_default(unique)
]
interface IDCompositionDevice : IUnknown
{
    HRESULT Commit();
    HRESULT WaitForCommitCompletion();
    HRESULT GetFrameStatistics([out] DCOMPOSITION_FRAME_STATISTICS *statistics);
    HRESULT CreateTargetForHwnd([in] HWND hwnd, [in] BOOL topmost, [out] IDCompositionTarget **target);
    HRESULT CreateVisual([out] IDCompositionVisual **visual);
    HRESULT CreateSurface([in] UINT width, [in] UINT height, [in] DXGI_FORMAT pixel_format, [in] DXGI_ALPHA_MODE alpha_mode, [out] IDCompositionSurface **surface);
    HRESULT CreateVirtualSurface([in] UINT width, [in] UINT height, [in] DXGI_FORMAT pixel_format, [in] DXGI_ALPHA_MODE alpha_mode, [out] IDCompositionVirtualSurface **surface);
    HRESULT CreateSurfaceFromHandle([in] HANDLE handle, [out] IUnknown **surface);
    HRESULT CreateSurfaceFromHwnd([in] HWND hwnd, [out] IUnknown **surface);
    HRESULT CreateTranslateTransform([out] IDCompositionTranslateTransform **transform);
    HRESULT CreateScaleTransform([out] IDCompositionScaleTransform **transform);
    HRESULT CreateRotateTransform([out] IDCompositionRotateTransform **transform);
    HRESULT CreateSkewTransform([out] IDCompositionSkewTransform **transform);
    HRESULT CreateMatrixTransform([out] IDCompositionMatrixTransform **transform);
    HRESULT CreateTransformGroup([in, size_is(elements)] IDCompositionTransform **transforms, [in] UINT elements, [out] IDCompositionTransform **transform_group);
    HRESULT CreateTranslateTransform3D([out] IDCompositionTranslateTransform3D **transform_3d);
    HRESULT CreateScaleTransform3D([out] IDCompositionScaleTransform3D **transform_3d);
    HRESULT CreateRotateTransform3D([out] IDCompositionRotateTransform3D **transform_3d);
    HRESULT CreateMatrixTransform3D([out] IDCompositionMatrixTransform3D **transform_3d);
    HRESULT CreateTransform3DGroup([in, size_is(elements)] IDCompositionTransform3D **transforms_3d, [in] UINT elements, [out] IDCompositionTransform3D **transform_3d_group);
    HRESULT CreateEffectGroup([out] IDCompositionEffectGroup **effect_group);
    HRESULT CreateRectangleClip([out] IDCompositionRectangleClip **clip);
    HRESULT CreateAnimation([out] IDCompositionAnimation **animation);
    HRESULT CheckDeviceState([out] BOOL *valid);
}

[
    object,
    uuid(75f6468d-1b8e-447c-9bc6-75fea80b5b25),
    local,
    pointer_default(unique)
]
interface IDCompositionDevice2 : IUnknown
{
    HRESULT Commit();
    HRESULT WaitForCommitCompletion();
    HRESULT GetFrameStatistics([out] DCOMPOSITION_FRAME_STATISTICS *statistics);
    HRESULT CreateVisual([out] IDCompositionVisual2 **visual);
    HRESULT CreateSurfaceFactory([in] IUnknown *rendering_device, [out] IDCompositionSurfaceFactory **surface_factory);
    HRESULT CreateSurface([in] UINT width, [in] UINT height, [in] DXGI_FORMAT pixel_format, [in] DXGI_ALPHA_MODE alpha_mode, [out] IDCompositionSurface **surface);
    HRESULT CreateVirtualSurface([in] UINT width, [in] UINT height, [in] DXGI_FORMAT pixel_format, [in] DXGI_ALPHA_MODE alpha_mode, [out] IDCompositionVirtualSurface **surface);
    HRESULT CreateTranslateTransform([out] IDCompositionTranslateTransform **transform);
    HRESULT CreateScaleTransform([out] IDCompositionScaleTransform **transform);
    HRESULT CreateRotateTransform([out] IDCompositionRotateTransform **transform);
    HRESULT CreateSkewTransform([out] IDCompositionSkewTransform **transform);
    HRESULT CreateMatrixTransform([out] IDCompositionMatrixTransform **transform);
    HRESULT CreateTransformGroup([in, size_is(elements)] IDCompositionTransform **transforms, [in] UINT elements, [out] IDCompositionTransform **transform_group);
    HRESULT CreateTranslateTransform3D([out] IDCompositionTranslateTransform3D **transform_3d);
    HRESULT CreateScaleTransform3D([out] IDCompositionScaleTransform3D **transform_3d);
    HRESULT CreateRotateTransform3D([out] IDCompositionRotateTransform3D **transform_3d);
    HRESULT CreateMatrixTransform3D([out] IDCompositionMatrixTransform3D **transform_3d);
    HRESULT CreateTransform3DGroup([in, size_is(elements)] IDCompositionTransform3D **transforms_3d, [in] UINT elements, [out] IDCompositionTransform3D **transform_3d_group);
    HRESULT CreateEffectGroup([out] IDCompositionEffectGroup **effect_group);
    HRESULT CreateRectangleClip([out] IDCompositionRectangleClip **clip);
    HRESULT CreateAnimation([out] IDCompositionAnimation **animation);
}

[
    object,
    uuid(5f4633fe-1e08-4cb8-8c75-ce24333f5602),
    local,
    pointer_default(unique)
]
interface IDCompositionDesktopDevice : IDCompositionDevice2
{
    HRESULT CreateTargetForHwnd([in] HWND hwnd, [in] BOOL topmost, [out] IDCompositionTarget **target);
    HRESULT CreateSurfaceFromHandle([in] HANDLE handle, [out] IUnknown **surface);
    HRESULT CreateSurfaceFromHwnd([in] HWND hwnd, [out] IUnknown **surface);
}

cpp_quote("STDAPI DCompositionCreateDevice(IDXGIDevice *dxgi_device, REFIID iid, void **device);")
cpp_quote("STDAPI DCompositionCreateDevice2(IUnknown *rendering_device, REFIID iid, void **device);")