/*
 * Copyright 2002-2003 Jason Edmeades
 *                     Raphael Junqueira
 *
 * 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 "d3d8_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d8);

static void STDMETHODCALLTYPE d3d8_vertexshader_wined3d_object_destroyed(void *parent)
{
    struct d3d8_vertex_shader *shader = parent;
    d3d8_vertex_declaration_destroy(shader->vertex_declaration);
    HeapFree(GetProcessHeap(), 0, shader);
}

void d3d8_vertex_shader_destroy(struct d3d8_vertex_shader *shader)
{
    TRACE("shader %p.\n", shader);

    if (shader->wined3d_shader)
    {
        wined3d_mutex_lock();
        wined3d_shader_decref(shader->wined3d_shader);
        wined3d_mutex_unlock();
    }
    else
    {
        d3d8_vertexshader_wined3d_object_destroyed(shader);
    }
}

static const struct wined3d_parent_ops d3d8_vertexshader_wined3d_parent_ops =
{
    d3d8_vertexshader_wined3d_object_destroyed,
};

static HRESULT d3d8_vertexshader_create_vertexdeclaration(struct d3d8_device *device,
        const DWORD *declaration, DWORD shader_handle, struct d3d8_vertex_declaration **decl_ptr)
{
    struct d3d8_vertex_declaration *object;
    HRESULT hr;

    TRACE("device %p, declaration %p, shader_handle %#x, decl_ptr %p.\n",
            device, declaration, shader_handle, decl_ptr);

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
    if (!object)
    {
        ERR("Memory allocation failed.\n");
        return E_OUTOFMEMORY;
    }

    hr = d3d8_vertex_declaration_init(object, device, declaration, shader_handle);
    if (FAILED(hr))
    {
        WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
        HeapFree(GetProcessHeap(), 0, object);
        return hr;
    }

    TRACE("Created vertex declaration %p.\n", object);
    *decl_ptr = object;

    return D3D_OK;
}

HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_device *device,
        const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage)
{
    const DWORD *token = declaration;
    HRESULT hr;

    /* Test if the vertex declaration is valid. */
    while (D3DVSD_END() != *token)
    {
        D3DVSD_TOKENTYPE token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);

        if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000))
        {
            DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
            DWORD reg  = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);

            if (reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !byte_code)
            {
                WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n");
                return D3DERR_INVALIDCALL;
            }
        }
        token += parse_token(token);
    }

    hr = d3d8_vertexshader_create_vertexdeclaration(device, declaration, shader_handle, &shader->vertex_declaration);
    if (FAILED(hr))
    {
        WARN("Failed to create vertex declaration, hr %#x.\n", hr);
        return hr;
    }

    if (byte_code)
    {
        if (usage) FIXME("Usage %#x not implemented.\n", usage);

        wined3d_mutex_lock();
        hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL /* output signature */,
                shader, &d3d8_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 1);
        wined3d_mutex_unlock();
        if (FAILED(hr))
        {
            WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
            d3d8_vertex_declaration_destroy(shader->vertex_declaration);
            return hr;
        }

        load_local_constants(declaration, shader->wined3d_shader);
    }

    return D3D_OK;
}

static void STDMETHODCALLTYPE d3d8_pixelshader_wined3d_object_destroyed(void *parent)
{
    HeapFree(GetProcessHeap(), 0, parent);
}

void d3d8_pixel_shader_destroy(struct d3d8_pixel_shader *shader)
{
    TRACE("shader %p.\n", shader);

    wined3d_mutex_lock();
    wined3d_shader_decref(shader->wined3d_shader);
    wined3d_mutex_unlock();
}

static const struct wined3d_parent_ops d3d8_pixelshader_wined3d_parent_ops =
{
    d3d8_pixelshader_wined3d_object_destroyed,
};

HRESULT d3d8_pixel_shader_init(struct d3d8_pixel_shader *shader, struct d3d8_device *device,
        const DWORD *byte_code, DWORD shader_handle)
{
    HRESULT hr;

    shader->handle = shader_handle;

    wined3d_mutex_lock();
    hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader,
            &d3d8_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 1);
    wined3d_mutex_unlock();
    if (FAILED(hr))
    {
        WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr);
        return hr;
    }

    return D3D_OK;
}
