/*              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->type == WINED3D_RTYPE_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;
}
