/*
 * Copyright 2000 (c) Marcus Meissner
 * Copyright 2000 (c) TransGaming Technologies Inc.
 * Copyright 2006 (c) Stefan Dösinger
 *
 * 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
 */

#include "config.h"
#include <stdio.h>
#ifdef HAVE_FLOAT_H
# include <float.h>
#endif
#include "wined3d_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d);

ULONG CDECL wined3d_clipper_incref(struct wined3d_clipper *clipper)
{
    ULONG refcount = InterlockedIncrement(&clipper->ref);

    TRACE("%p increasing refcount to %u.\n", clipper, refcount);

    return refcount;
}

ULONG CDECL wined3d_clipper_decref(struct wined3d_clipper *clipper)
{
    ULONG refcount = InterlockedDecrement(&clipper->ref);

    TRACE("%p decreasing refcount to %u.\n", clipper, refcount);

    if (!refcount)
        HeapFree(GetProcessHeap(), 0, clipper);

    return refcount;
}

HRESULT CDECL wined3d_clipper_set_window(struct wined3d_clipper *clipper, DWORD flags, HWND window)
{
    TRACE("clipper %p, flags %#x, window %p.\n", clipper, flags, window);

    if (flags)
    {
        FIXME("flags %#x, not supported.\n", flags);
        return WINED3DERR_INVALIDCALL;
    }

    clipper->hWnd = window;

    return WINED3D_OK;
}

HRESULT CDECL wined3d_clipper_get_clip_list(const struct wined3d_clipper *clipper, const RECT *rect,
        RGNDATA *clip_list, DWORD *clip_list_size)
{
    TRACE("clipper %p, rect %s, clip_list %p, clip_list_size %p.\n",
            clipper, wine_dbgstr_rect(rect), clip_list, clip_list_size);

    if (clipper->hWnd)
    {
        HDC hDC = GetDCEx(clipper->hWnd, NULL, DCX_WINDOW);
        if (hDC)
        {
            HRGN hRgn = CreateRectRgn(0,0,0,0);
            if (GetRandomRgn(hDC, hRgn, SYSRGN))
            {
                if (GetVersion() & 0x80000000)
                {
                    /* map region to screen coordinates */
                    POINT org;
                    GetDCOrgEx(hDC, &org);
                    OffsetRgn(hRgn, org.x, org.y);
                }
                if (rect)
                {
                    HRGN hRgnClip = CreateRectRgn(rect->left, rect->top,
                            rect->right, rect->bottom);
                    CombineRgn(hRgn, hRgn, hRgnClip, RGN_AND);
                    DeleteObject(hRgnClip);
                }
                *clip_list_size = GetRegionData(hRgn, *clip_list_size, clip_list);
            }
            DeleteObject(hRgn);
            ReleaseDC(clipper->hWnd, hDC);
        }
        return WINED3D_OK;
    }
    else
    {
        static unsigned int once;

        if (!once++)
            FIXME("clipper %p, rect %s, clip_list %p, clip_list_size %p stub!\n",
                    clipper, wine_dbgstr_rect(rect), clip_list, clip_list_size);

        if (clip_list_size)
            *clip_list_size = 0;

        return WINEDDERR_NOCLIPLIST;
    }
}

HRESULT CDECL wined3d_clipper_set_clip_list(struct wined3d_clipper *clipper, const RGNDATA *region, DWORD flags)
{
    static unsigned int once;

    if (!once++ || !region)
        FIXME("clipper %p, region %p, flags %#x stub!\n", clipper, region, flags);

    return WINED3D_OK;
}

HRESULT CDECL wined3d_clipper_get_window(const struct wined3d_clipper *clipper, HWND *window)
{
    TRACE("clipper %p, window %p.\n", clipper, window);

    *window = clipper->hWnd;

    return WINED3D_OK;
}

HRESULT CDECL wined3d_clipper_is_clip_list_changed(const struct wined3d_clipper *clipper, BOOL *changed)
{
    FIXME("clipper %p, changed %p stub!\n", clipper, changed);

    /* XXX What is safest? */
    *changed = FALSE;

    return WINED3D_OK;
}

struct wined3d_clipper * CDECL wined3d_clipper_create(void)
{
    struct wined3d_clipper *clipper;

    TRACE("\n");

    clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*clipper));
    if (!clipper)
    {
        ERR("Out of memory when trying to allocate a WineD3D Clipper\n");
        return NULL;
    }

    wined3d_clipper_incref(clipper);

    return clipper;
}
