/*              DirectDraw - IDirectPalette base interface
 *
 * Copyright 1997-2000 Marcus Meissner
 * Copyright 2000-2001 TransGaming Technologies Inc.
 * Copyright 2006 Stefan Dösinger 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
 */
#include "config.h"
#include "winerror.h"
#include "wine/debug.h"

#include <string.h>

#include "wined3d_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d);

#define SIZE_BITS (WINEDDPCAPS_1BIT | WINEDDPCAPS_2BIT | WINEDDPCAPS_4BIT | WINEDDPCAPS_8BIT)

ULONG CDECL wined3d_palette_incref(struct wined3d_palette *palette)
{
    ULONG refcount = InterlockedIncrement(&palette->ref);

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

    return refcount;
}

ULONG CDECL wined3d_palette_decref(struct wined3d_palette *palette)
{
    ULONG refcount = InterlockedDecrement(&palette->ref);

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

    if (!refcount)
    {
        DeleteObject(palette->hpal);
        HeapFree(GetProcessHeap(), 0, palette);
    }

    return refcount;
}

static WORD wined3d_palette_size(DWORD flags)
{
    switch (flags & SIZE_BITS)
    {
        case WINEDDPCAPS_1BIT: return 2;
        case WINEDDPCAPS_2BIT: return 4;
        case WINEDDPCAPS_4BIT: return 16;
        case WINEDDPCAPS_8BIT: return 256;
        default:
            FIXME("Unhandled size bits %#x.\n", flags & SIZE_BITS);
            return 256;
    }
}

HRESULT CDECL wined3d_palette_get_entries(const struct wined3d_palette *palette,
        DWORD flags, DWORD start, DWORD count, PALETTEENTRY *entries)
{
    TRACE("palette %p, flags %#x, start %u, count %u, entries %p.\n",
            palette, flags, start, count, entries);

    if (flags) return WINED3DERR_INVALIDCALL; /* unchecked */
    if (start + count > wined3d_palette_size(palette->flags))
        return WINED3DERR_INVALIDCALL;

    if (palette->flags & WINEDDPCAPS_8BITENTRIES)
    {
        BYTE *entry = (BYTE *)entries;
        unsigned int i;

        for (i = start; i < count + start; ++i)
            *entry++ = palette->palents[i].peRed;
    }
    else
        memcpy(entries, palette->palents + start, count * sizeof(*entries));

    return WINED3D_OK;
}

HRESULT CDECL wined3d_palette_set_entries(struct wined3d_palette *palette,
        DWORD flags, DWORD start, DWORD count, const PALETTEENTRY *entries)
{
    struct wined3d_resource *resource;

    TRACE("palette %p, flags %#x, start %u, count %u, entries %p.\n",
            palette, flags, start, count, entries);
    TRACE("Palette flags: %#x.\n", palette->flags);

    if (palette->flags & WINEDDPCAPS_8BITENTRIES)
    {
        const BYTE *entry = (const BYTE *)entries;
        unsigned int i;

        for (i = start; i < count + start; ++i)
            palette->palents[i].peRed = *entry++;
    }
    else
    {
        memcpy(palette->palents + start, entries, count * sizeof(*palette->palents));

        /* When WINEDDCAPS_ALLOW256 isn't set we need to override entry 0 with black and 255 with white */
        if (!(palette->flags & WINEDDPCAPS_ALLOW256))
        {
            TRACE("WINEDDPCAPS_ALLOW256 set, overriding palette entry 0 with black and 255 with white\n");
            palette->palents[0].peRed = 0;
            palette->palents[0].peGreen = 0;
            palette->palents[0].peBlue = 0;

            palette->palents[255].peRed = 255;
            palette->palents[255].peGreen = 255;
            palette->palents[255].peBlue = 255;
        }

        if (palette->hpal)
            SetPaletteEntries(palette->hpal, start, count, palette->palents + start);
    }

    /* If the palette is attached to the render target, update all render targets */
    LIST_FOR_EACH_ENTRY(resource, &palette->device->resources, struct wined3d_resource, resource_list_entry)
    {
        if (resource->resourceType == WINED3DRTYPE_SURFACE)
        {
            struct wined3d_surface *surface = surface_from_resource(resource);
            if (surface->palette == palette)
                surface->surface_ops->surface_realize_palette(surface);
        }
    }

    return WINED3D_OK;
}

DWORD CDECL wined3d_palette_get_flags(const struct wined3d_palette *palette)
{
    TRACE("palette %p.\n", palette);

    return palette->flags;
}

void * CDECL wined3d_palette_get_parent(const struct wined3d_palette *palette)
{
    TRACE("palette %p.\n", palette);

    return palette->parent;
}

static HRESULT wined3d_palette_init(struct wined3d_palette *palette, struct wined3d_device *device,
        DWORD flags, const PALETTEENTRY *entries, void *parent)
{
    HRESULT hr;

    palette->ref = 1;
    palette->parent = parent;
    palette->device = device;
    palette->flags = flags;

    palette->palNumEntries = wined3d_palette_size(flags);
    palette->hpal = CreatePalette((const LOGPALETTE *)&palette->palVersion);
    if (!palette->hpal)
    {
        WARN("Failed to create palette.\n");
        return E_FAIL;
    }

    hr = wined3d_palette_set_entries(palette, 0, 0, wined3d_palette_size(flags), entries);
    if (FAILED(hr))
    {
        WARN("Failed to set palette entries, hr %#x.\n", hr);
        DeleteObject(palette->hpal);
        return hr;
    }

    return WINED3D_OK;
}

HRESULT CDECL wined3d_palette_create(struct wined3d_device *device, DWORD flags,
        const PALETTEENTRY *entries, void *parent, struct wined3d_palette **palette)
{
    struct wined3d_palette *object;
    HRESULT hr;

    TRACE("device %p, flags %#x, entries %p, palette %p, parent %p.\n",
            device, flags, entries, palette, parent);

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Failed to allocate palette memory.\n");
        return E_OUTOFMEMORY;
    }

    hr = wined3d_palette_init(object, device, flags, entries, parent);
    if (FAILED(hr))
    {
        WARN("Failed to initialize palette, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created palette %p.\n", object);
    *palette = object;

    return WINED3D_OK;
}
