/*
 * Direct3D9 index buffers
 * Copyright (c) 2003, TransGaming Technologies Inc.
 */

#include "config.h"

#include "winbase.h"
#include "d3d9.h"
#include "wine/debug.h"

#include "d3d9_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(ddraw);

HRESULT WINAPI Direct3DIndexBuffer9_QueryInterface(LPDIRECT3DINDEXBUFFER9 iface,
						   REFIID riid,
						   LPVOID* obj)
{
  ICOM_THIS(IDirect3DIndexBuffer9Impl, iface);
  TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), obj);
  if (IsEqualGUID(&IID_IUnknown, riid) ||
      IsEqualGUID(&IID_IDirect3DResource9, riid) ||
      IsEqualGUID(&IID_IDirect3DIndexBuffer9, riid)) {
    This->ref++;
    *obj = This;
    return S_OK;
  }
  else {
    FIXME("(%p)->(%s): no interface", iface, debugstr_guid(riid));
    return E_NOINTERFACE;
  }
}

ULONG WINAPI Direct3DIndexBuffer9_AddRef(LPDIRECT3DINDEXBUFFER9 iface)
{
  ICOM_THIS(IDirect3DIndexBuffer9Impl, iface);
  TRACE("(%p)->()\n", iface);
  return ++This->ref - This->intref;
}

ULONG WINAPI Direct3DIndexBuffer9_Release(LPDIRECT3DINDEXBUFFER9 iface)
{
  ICOM_THIS(IDirect3DIndexBuffer9Impl, iface);

  TRACE("(%p)->()\n", iface);
  if (--This->ref) return This->ref - This->intref;

  HeapFree(buffer_heap, 0, This->ptr);
  HeapFree(GetProcessHeap(), 0, This);
  return 0;
}

HRESULT WINAPI Direct3DIndexBuffer9_Lock(LPDIRECT3DINDEXBUFFER9 iface,
					 UINT OffsetToLock,
					 UINT SizeToLock,
					 void** ppbData,
					 DWORD Flags)
{
  ICOM_THIS(IDirect3DIndexBuffer9Impl, iface);

  TRACE("(%p)->(%d,%d,%p,%ld)\n", iface,
	OffsetToLock, SizeToLock, ppbData, Flags);

  *ppbData = This->ptr + OffsetToLock;

  TRACE("returning: bits %p\n", *ppbData);

  return D3D_OK;
}

HRESULT WINAPI Direct3DIndexBuffer9_Unlock(LPDIRECT3DINDEXBUFFER9 iface)
{
  /* ICOM_THIS(IDirect3DIndexBuffer9Impl, iface); */

  TRACE("(%p)->()\n", iface);

  return D3D_OK;
}

HRESULT WINAPI Direct3DIndexBuffer9_GetDesc(LPDIRECT3DINDEXBUFFER9 iface,
					    D3DINDEXBUFFER_DESC* pDesc)
{
  ICOM_THIS(IDirect3DIndexBuffer9Impl, iface);

  TRACE("(%p)->(%p)\n", iface, pDesc);
  pDesc->Format = This->Format;
  pDesc->Type = D3DRTYPE_INDEXBUFFER;
  pDesc->Usage = This->Usage;
  pDesc->Pool = D3DPOOL_DEFAULT;
  pDesc->Size = This->t.gbl.u4.dwLinearSize;
  return D3D_OK;
}

static ICOM_VTABLE(IDirect3DIndexBuffer9) D3DIB9_Vtbl =
{
  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
  Direct3DIndexBuffer9_QueryInterface,
  Direct3DIndexBuffer9_AddRef,
  Direct3DIndexBuffer9_Release,
  (void*)0xdead6004, /* GetDevice */
  (void*)0xdead6005, /* SetPrivateData */
  (void*)0xdead6006, /* GetPrivateData */
  (void*)0xdead6007, /* FreePrivateData */
  (void*)0xdead6008, /* SetPriority */
  (void*)0xdead600a, /* GetPriority */
  (void*)0xdead600b, /* PreLoad */
  (void*)0xdead600c, /* GetType */
  Direct3DIndexBuffer9_Lock,
  Direct3DIndexBuffer9_Unlock,
  Direct3DIndexBuffer9_GetDesc
};

HRESULT WINAPI Direct3DDevice9_CreateIndexBuffer(LPDIRECT3DDEVICE9 iface,
						 UINT Length,
						 DWORD Usage,
						 D3DFORMAT Format,
						 D3DPOOL Pool,
						 IDirect3DIndexBuffer9** ppIndexBuffer,
						 HANDLE* pSharedHandle)
{
  ICOM_THIS(IDirect3DDevice9Impl, iface);
  IDirect3DIndexBuffer9Impl *pIdxBuf;

  TRACE("(%p}->(%d,%ld,0x%x,%d,%p,%p)\n", iface, Length,
	Usage, Format, Pool, ppIndexBuffer, pSharedHandle);

  pIdxBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer9Impl));
  pIdxBuf->lpVtbl = &D3DIB9_Vtbl;
  pIdxBuf->ref = 1;
  pIdxBuf->intref = 0;
  pIdxBuf->parent = This;
  pIdxBuf->Format = Format;
  pIdxBuf->Usage = Usage;

  pIdxBuf->t.lcl.lpSurfMore = &pIdxBuf->t.more;
  pIdxBuf->t.lcl.lpGbl = &pIdxBuf->t.gbl;
  pIdxBuf->t.lcl.dwFlags = 0; /* FIXME */
  pIdxBuf->t.lcl.ddsCaps.dwCaps = DDSCAPS_EXECUTEBUFFER;
  pIdxBuf->t.more.lpDD_lcl = &This->local;
  pIdxBuf->t.more.ddsCapsEx.dwCaps2 = DDSCAPS2_VERTEXBUFFER;
  pIdxBuf->t.more.ddsCapsEx.dwCaps3 = 0;
  pIdxBuf->t.more.ddsCapsEx.dwCaps4 = 0;
  pIdxBuf->t.gmore = &pIdxBuf->t.gbl_more;
  pIdxBuf->t.gbl.u3.lpDD = This->local.lpGbl;
  pIdxBuf->t.gbl.u4.dwLinearSize = Length;

  /* FIXME: set more caps bits */

  /* hack */
  TRACE("allocating %d bytes\n", Length);
  pIdxBuf->ptr = HeapAlloc(buffer_heap, HEAP_ZERO_MEMORY, Length);

  TRACE("created %p\n", pIdxBuf);
  *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER9)pIdxBuf;
  return D3D_OK;
}
