/*
 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 * license, and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE. */

#include "device9.h"
#include "volume9.h"
#include "basetexture9.h" /* for marking dirty */
#include "volumetexture9.h"
#include "nine_helpers.h"
#include "nine_pipe.h"
#include "nine_dump.h"

#include "util/u_format.h"
#include "util/u_surface.h"

#define DBG_CHANNEL DBG_VOLUME


static HRESULT
NineVolume9_AllocateData( struct NineVolume9 *This )
{
    unsigned size = This->layer_stride * This->desc.Depth;

    DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n",
        This->base.container, This, This->level, size);

    This->data = (uint8_t *)align_calloc(size, 32);
    if (!This->data)
        return E_OUTOFMEMORY;
    return D3D_OK;
}

static HRESULT
NineVolume9_ctor( struct NineVolume9 *This,
                  struct NineUnknownParams *pParams,
                  struct NineUnknown *pContainer,
                  struct pipe_resource *pResource,
                  unsigned Level,
                  D3DVOLUME_DESC *pDesc )
{
    HRESULT hr;

    assert(pContainer); /* stand-alone volumes can't be created */

    DBG("This=%p pContainer=%p pDevice=%p pResource=%p Level=%u pDesc=%p\n",
        This, pContainer, pParams->device, pResource, Level, pDesc);

    /* Mark this as a special surface held by another internal resource. */
    pParams->container = pContainer;

    user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) ||
                (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL);

    assert(pResource || pDesc->Pool != D3DPOOL_DEFAULT);

    hr = NineUnknown_ctor(&This->base, pParams);
    if (FAILED(hr))
        return hr;

    pipe_resource_reference(&This->resource, pResource);

    This->transfer = NULL;
    This->lock_count = 0;

    This->level = Level;
    This->level_actual = Level;
    This->desc = *pDesc;

    This->info.screen = pParams->device->screen;
    This->info.target = PIPE_TEXTURE_3D;
    This->info.width0 = pDesc->Width;
    This->info.height0 = pDesc->Height;
    This->info.depth0 = pDesc->Depth;
    This->info.last_level = 0;
    This->info.array_size = 1;
    This->info.nr_samples = 0;
    This->info.usage = PIPE_USAGE_DEFAULT;
    This->info.bind = PIPE_BIND_SAMPLER_VIEW;
    This->info.flags = 0;
    This->info.format = d3d9_to_pipe_format_checked(This->info.screen,
                                                    pDesc->Format,
                                                    This->info.target,
                                                    This->info.nr_samples,
                                                    This->info.bind, FALSE,
                                                    pDesc->Pool == D3DPOOL_SCRATCH);

    if (This->info.format == PIPE_FORMAT_NONE)
        return D3DERR_DRIVERINTERNALERROR;

    This->stride = util_format_get_stride(This->info.format, pDesc->Width);
    This->stride = align(This->stride, 4);
    This->layer_stride = util_format_get_2d_size(This->info.format,
                                                 This->stride, pDesc->Height);

    /* Get true format */
    This->format_conversion = d3d9_to_pipe_format_checked(This->info.screen,
                                                         pDesc->Format,
                                                         This->info.target,
                                                         This->info.nr_samples,
                                                         This->info.bind, FALSE,
                                                         TRUE);
    if (This->info.format != This->format_conversion) {
        This->stride_conversion = nine_format_get_stride(This->format_conversion,
                                                         pDesc->Width);
        This->layer_stride_conversion = util_format_get_2d_size(This->format_conversion,
                                                                This->stride_conversion,
                                                                pDesc->Height);
        This->data_conversion = align_calloc(This->layer_stride_conversion *
                                             This->desc.Depth, 32);
        if (!This->data_conversion)
            return E_OUTOFMEMORY;
    }

    if (!This->resource) {
        hr = NineVolume9_AllocateData(This);
        if (FAILED(hr))
            return hr;
    }
    return D3D_OK;
}

static void
NineVolume9_dtor( struct NineVolume9 *This )
{
    DBG("This=%p\n", This);

    if (This->transfer)
        NineVolume9_UnlockBox(This);

    if (This->data)
        align_free(This->data);
    if (This->data_conversion)
        align_free(This->data_conversion);

    pipe_resource_reference(&This->resource, NULL);

    NineUnknown_dtor(&This->base);
}

HRESULT NINE_WINAPI
NineVolume9_GetContainer( struct NineVolume9 *This,
                          REFIID riid,
                          void **ppContainer )
{
    char guid_str[64];

    DBG("This=%p riid=%p id=%s ppContainer=%p\n",
        This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer);

    (void)guid_str;

    if (!NineUnknown(This)->container)
        return E_NOINTERFACE;
    return NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer);
}

static inline void
NineVolume9_MarkContainerDirty( struct NineVolume9 *This )
{
    struct NineBaseTexture9 *tex;
#ifdef DEBUG
    /* This is always contained by a NineVolumeTexture9. */
    GUID id = IID_IDirect3DVolumeTexture9;
    REFIID ref = &id;
    assert(NineUnknown_QueryInterface(This->base.container, ref, (void **)&tex)
           == S_OK);
    assert(NineUnknown_Release(NineUnknown(tex)) != 0);
#endif

    tex = NineBaseTexture9(This->base.container);
    assert(tex);
    if (This->desc.Pool == D3DPOOL_MANAGED)
        tex->managed.dirty = TRUE;

    BASETEX_REGISTER_UPDATE(tex);
}

HRESULT NINE_WINAPI
NineVolume9_GetDesc( struct NineVolume9 *This,
                     D3DVOLUME_DESC *pDesc )
{
    user_assert(pDesc != NULL, E_POINTER);
    *pDesc = This->desc;
    return D3D_OK;
}

inline void
NineVolume9_AddDirtyRegion( struct NineVolume9 *This,
                            const struct pipe_box *box )
{
    D3DBOX dirty_region;
    struct NineVolumeTexture9 *tex = NineVolumeTexture9(This->base.container);

    if (!box) {
        NineVolumeTexture9_AddDirtyBox(tex, NULL);
    } else {
        dirty_region.Left = box->x << This->level_actual;
        dirty_region.Top = box->y << This->level_actual;
        dirty_region.Front = box->z << This->level_actual;
        dirty_region.Right = dirty_region.Left + (box->width << This->level_actual);
        dirty_region.Bottom = dirty_region.Top + (box->height << This->level_actual);
        dirty_region.Back = dirty_region.Front + (box->depth << This->level_actual);
        NineVolumeTexture9_AddDirtyBox(tex, &dirty_region);
    }
}

static inline uint8_t *
NineVolume9_GetSystemMemPointer(struct NineVolume9 *This, int x, int y, int z)
{
    unsigned x_offset = util_format_get_stride(This->info.format, x);

    y = util_format_get_nblocksy(This->info.format, y);

    assert(This->data);
    return This->data + (z * This->layer_stride + y * This->stride + x_offset);
}

HRESULT NINE_WINAPI
NineVolume9_LockBox( struct NineVolume9 *This,
                     D3DLOCKED_BOX *pLockedVolume,
                     const D3DBOX *pBox,
                     DWORD Flags )
{
    struct pipe_context *pipe;
    struct pipe_resource *resource = This->resource;
    struct pipe_box box;
    unsigned usage;

    DBG("This=%p(%p) pLockedVolume=%p pBox=%p[%u..%u,%u..%u,%u..%u] Flags=%s\n",
        This, This->base.container, pLockedVolume, pBox,
        pBox ? pBox->Left : 0, pBox ? pBox->Right : 0,
        pBox ? pBox->Top : 0, pBox ? pBox->Bottom : 0,
        pBox ? pBox->Front : 0, pBox ? pBox->Back : 0,
        nine_D3DLOCK_to_str(Flags));

    /* check if it's already locked */
    user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);

    /* set pBits to NULL after lock_count check */
    user_assert(pLockedVolume, E_POINTER);
    pLockedVolume->pBits = NULL;

    user_assert(This->desc.Pool != D3DPOOL_DEFAULT ||
                (This->desc.Usage & D3DUSAGE_DYNAMIC), D3DERR_INVALIDCALL);

    user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)),
                D3DERR_INVALIDCALL);

    if (pBox && compressed_format (This->desc.Format)) { /* For volume all pools are checked */
        const unsigned w = util_format_get_blockwidth(This->info.format);
        const unsigned h = util_format_get_blockheight(This->info.format);
        user_assert((pBox->Left == 0 && pBox->Right == This->desc.Width &&
                     pBox->Top == 0 && pBox->Bottom == This->desc.Height) ||
                    (!(pBox->Left % w) && !(pBox->Right % w) &&
                     !(pBox->Top % h) && !(pBox->Bottom % h)),
                    D3DERR_INVALIDCALL);
    }

    if (Flags & D3DLOCK_DISCARD) {
        usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE;
    } else {
        usage = (Flags & D3DLOCK_READONLY) ?
            PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE;
    }
    if (Flags & D3DLOCK_DONOTWAIT)
        usage |= PIPE_TRANSFER_DONTBLOCK;

    if (pBox) {
        user_assert(pBox->Right > pBox->Left, D3DERR_INVALIDCALL);
        user_assert(pBox->Bottom > pBox->Top, D3DERR_INVALIDCALL);
        user_assert(pBox->Back > pBox->Front, D3DERR_INVALIDCALL);
        user_assert(pBox->Right <= This->desc.Width, D3DERR_INVALIDCALL);
        user_assert(pBox->Bottom <= This->desc.Height, D3DERR_INVALIDCALL);
        user_assert(pBox->Back <= This->desc.Depth, D3DERR_INVALIDCALL);

        d3dbox_to_pipe_box(&box, pBox);
        if (u_box_clip_2d(&box, &box, This->desc.Width, This->desc.Height) < 0) {
            DBG("Locked volume intersection empty.\n");
            return D3DERR_INVALIDCALL;
        }
    } else {
        u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth,
                 &box);
    }

    if (This->data_conversion) {
        /* For now we only have uncompressed formats here */
        pLockedVolume->RowPitch = This->stride_conversion;
        pLockedVolume->SlicePitch = This->layer_stride_conversion;
        pLockedVolume->pBits = This->data_conversion + box.z * This->layer_stride_conversion +
                               box.y * This->stride_conversion +
                               util_format_get_stride(This->format_conversion, box.x);
    } else if (This->data) {
        pLockedVolume->RowPitch = This->stride;
        pLockedVolume->SlicePitch = This->layer_stride;
        pLockedVolume->pBits =
            NineVolume9_GetSystemMemPointer(This, box.x, box.y, box.z);
    } else {
        pipe = NineDevice9_GetPipe(This->base.device);
        pLockedVolume->pBits =
            pipe->transfer_map(pipe, resource, This->level, usage,
                               &box, &This->transfer);
        if (!This->transfer) {
            if (Flags & D3DLOCK_DONOTWAIT)
                return D3DERR_WASSTILLDRAWING;
            return D3DERR_DRIVERINTERNALERROR;
        }
        pLockedVolume->RowPitch = This->transfer->stride;
        pLockedVolume->SlicePitch = This->transfer->layer_stride;
    }

    if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) {
        NineVolume9_MarkContainerDirty(This);
        NineVolume9_AddDirtyRegion(This, &box);
    }

    ++This->lock_count;
    return D3D_OK;
}

HRESULT NINE_WINAPI
NineVolume9_UnlockBox( struct NineVolume9 *This )
{
    struct pipe_context *pipe;

    DBG("This=%p lock_count=%u\n", This, This->lock_count);
    user_assert(This->lock_count, D3DERR_INVALIDCALL);
    if (This->transfer) {
        pipe = NineDevice9_GetPipe(This->base.device);
        pipe->transfer_unmap(pipe, This->transfer);
        This->transfer = NULL;
    }
    --This->lock_count;

    if (This->data_conversion) {
        struct pipe_transfer *transfer;
        uint8_t *dst = This->data;
        struct pipe_box box;

        u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth,
                 &box);

        pipe = NineDevice9_GetPipe(This->base.device);
        if (!dst) {
            dst = pipe->transfer_map(pipe,
                                     This->resource,
                                     This->level,
                                     PIPE_TRANSFER_WRITE |
                                     PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
                                     &box, &transfer);
            if (!dst)
                return D3D_OK;
        }

        (void) util_format_translate_3d(This->info.format,
                                        dst, This->data ? This->stride : transfer->stride,
                                        This->data ? This->layer_stride : transfer->layer_stride,
                                        0, 0, 0,
                                        This->format_conversion,
                                        This->data_conversion,
                                        This->stride_conversion,
                                        This->layer_stride_conversion,
                                        0, 0, 0,
                                        This->desc.Width, This->desc.Height,
                                        This->desc.Depth);

        if (!This->data)
            pipe_transfer_unmap(pipe, transfer);
    }

    return D3D_OK;
}

/* When this function is called, we have already checked
 * The copy regions fit the volumes */
void
NineVolume9_CopyMemToDefault( struct NineVolume9 *This,
                              struct NineVolume9 *From,
                              unsigned dstx, unsigned dsty, unsigned dstz,
                              struct pipe_box *pSrcBox )
{
    struct pipe_context *pipe;
    struct pipe_transfer *transfer = NULL;
    struct pipe_resource *r_dst = This->resource;
    struct pipe_box src_box;
    struct pipe_box dst_box;
    uint8_t *map = NULL;

    DBG("This=%p From=%p dstx=%u dsty=%u dstz=%u pSrcBox=%p\n",
        This, From, dstx, dsty, dstz, pSrcBox);

    assert(This->desc.Pool == D3DPOOL_DEFAULT &&
           From->desc.Pool == D3DPOOL_SYSTEMMEM);

    dst_box.x = dstx;
    dst_box.y = dsty;
    dst_box.z = dstz;

    if (pSrcBox) {
        src_box = *pSrcBox;
    } else {
        src_box.x = 0;
        src_box.y = 0;
        src_box.z = 0;
        src_box.width = From->desc.Width;
        src_box.height = From->desc.Height;
        src_box.depth = From->desc.Depth;
    }

    dst_box.width = src_box.width;
    dst_box.height = src_box.height;
    dst_box.depth = src_box.depth;

    pipe = NineDevice9_GetPipe(This->base.device);

    map = pipe->transfer_map(pipe,
                             r_dst,
                             This->level,
                             PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
                             &dst_box, &transfer);
    if (!map)
        return;

    /* Note: if formats are the sames, it will revert
     * to normal memcpy */
    (void) util_format_translate_3d(r_dst->format,
                                    map, transfer->stride,
                                    transfer->layer_stride,
                                    0, 0, 0,
                                    From->info.format,
                                    From->data, From->stride,
                                    From->layer_stride,
                                    src_box.x, src_box.y,
                                    src_box.z,
                                    src_box.width,
                                    src_box.height,
                                    src_box.depth);

    pipe_transfer_unmap(pipe, transfer);

    if (This->data_conversion)
        (void) util_format_translate_3d(This->format_conversion,
                                        This->data_conversion,
                                        This->stride_conversion,
                                        This->layer_stride_conversion,
                                        dstx, dsty, dstz,
                                        From->info.format,
                                        From->data, From->stride,
                                        From->layer_stride,
                                        src_box.x, src_box.y,
                                        src_box.z,
                                        src_box.width,
                                        src_box.height,
                                        src_box.depth);

    NineVolume9_MarkContainerDirty(This);

    return;
}

HRESULT
NineVolume9_UploadSelf( struct NineVolume9 *This,
                        const struct pipe_box *damaged )
{
    struct pipe_context *pipe;
    struct pipe_resource *res = This->resource;
    struct pipe_box box;
    uint8_t *ptr;

    DBG("This=%p damaged=%p data=%p res=%p\n", This, damaged,
        This->data, res);

    assert(This->desc.Pool == D3DPOOL_MANAGED);
    assert(res);

    if (damaged) {
        box = *damaged;
    } else {
        box.x = 0;
        box.y = 0;
        box.z = 0;
        box.width = This->desc.Width;
        box.height = This->desc.Height;
        box.depth = This->desc.Depth;
    }

    ptr = NineVolume9_GetSystemMemPointer(This, box.x, box.y, box.z);

    pipe = NineDevice9_GetPipe(This->base.device);
    pipe->texture_subdata(pipe, res, This->level, 0, &box,
                          ptr, This->stride, This->layer_stride);

    return D3D_OK;
}


IDirect3DVolume9Vtbl NineVolume9_vtable = {
    (void *)NineUnknown_QueryInterface,
    (void *)NineUnknown_AddRef,
    (void *)NineUnknown_Release,
    (void *)NineUnknown_GetDevice, /* actually part of Volume9 iface */
    (void *)NineUnknown_SetPrivateData,
    (void *)NineUnknown_GetPrivateData,
    (void *)NineUnknown_FreePrivateData,
    (void *)NineVolume9_GetContainer,
    (void *)NineVolume9_GetDesc,
    (void *)NineVolume9_LockBox,
    (void *)NineVolume9_UnlockBox
};

static const GUID *NineVolume9_IIDs[] = {
    &IID_IDirect3DVolume9,
    &IID_IUnknown,
    NULL
};

HRESULT
NineVolume9_new( struct NineDevice9 *pDevice,
                 struct NineUnknown *pContainer,
                 struct pipe_resource *pResource,
                 unsigned Level,
                 D3DVOLUME_DESC *pDesc,
                 struct NineVolume9 **ppOut )
{
    NINE_DEVICE_CHILD_NEW(Volume9, ppOut, pDevice, /* args */
                          pContainer, pResource, Level, pDesc);
}
