'   0 IDirect3DDevice2_QueryInterface(p,a,b)                 (p)->lpVtbl->QueryInterface(p,a,b)
'   1 IDirect3DDevice2_AddRef(p)                             (p)->lpVtbl->AddRef(p)
'   2 IDirect3DDevice2_Release(p)                            (p)->lpVtbl->Release(p)
'   3 IDirect3DDevice2_GetCaps(p,a,b)                        (p)->lpVtbl->GetCaps(p,a,b)
'   4 IDirect3DDevice2_SwapTextureHandles(p,a,b)             (p)->lpVtbl->SwapTextureHandles(p,a,b)
'   5 IDirect3DDevice2_GetStats(p,a)                         (p)->lpVtbl->GetStats(p,a)
'   6 IDirect3DDevice2_AddViewport(p,a)                      (p)->lpVtbl->AddViewport(p,a)
'   7 IDirect3DDevice2_DeleteViewport(p,a)                   (p)->lpVtbl->DeleteViewport(p,a)
'   8 IDirect3DDevice2_NextViewport(p,a,b,c)                 (p)->lpVtbl->NextViewport(p,a,b,c)
'   9 IDirect3DDevice2_EnumTextureFormats(p,a,b)             (p)->lpVtbl->EnumTextureFormats(p,a,b)
'  10 IDirect3DDevice2_BeginScene(p)                         (p)->lpVtbl->BeginScene(p)
'  11 IDirect3DDevice2_EndScene(p)                           (p)->lpVtbl->EndScene(p)
'  12 IDirect3DDevice2_GetDirect3D(p,a)                      (p)->lpVtbl->GetDirect3D(p,a)
'  13 IDirect3DDevice2_SetCurrentViewport(p,a)               (p)->lpVtbl->SetCurrentViewport(p,a)
'  14 IDirect3DDevice2_GetCurrentViewport(p,a)               (p)->lpVtbl->GetCurrentViewport(p,a)
'  15 IDirect3DDevice2_SetRenderTarget(p,a,b)                (p)->lpVtbl->SetRenderTarget(p,a,b)
'  16 IDirect3DDevice2_GetRenderTarget(p,a)                  (p)->lpVtbl->GetRenderTarget(p,a)
'  17 IDirect3DDevice2_Begin(p,a,b,c)                        (p)->lpVtbl->Begin(p,a,b,c)
'  18 IDirect3DDevice2_BeginIndexed(p,a,b,c,d,e)             (p)->lpVtbl->BeginIndexed(p,a,b,c,d,e)
'  19 IDirect3DDevice2_Vertex(p,a)                           (p)->lpVtbl->Vertex(p,a)
'  20 IDirect3DDevice2_Index(p,a)                            (p)->lpVtbl->Index(p,a)
'  21 IDirect3DDevice2_End(p,a)                              (p)->lpVtbl->End(p,a)
'  22 IDirect3DDevice2_GetRenderState(p,a,b)                 (p)->lpVtbl->GetRenderState(p,a,b)
'  23 IDirect3DDevice2_SetRenderState(p,a,b)                 (p)->lpVtbl->SetRenderState(p,a,b)
'  24 IDirect3DDevice2_GetLightState(p,a,b)                  (p)->lpVtbl->GetLightState(p,a,b)
'  25 IDirect3DDevice2_SetLightState(p,a,b)                  (p)->lpVtbl->SetLightState(p,a,b)
'  26 IDirect3DDevice2_SetTransform(p,a,b)                   (p)->lpVtbl->SetTransform(p,a,b)
'  27 IDirect3DDevice2_GetTransform(p,a,b)                   (p)->lpVtbl->GetTransform(p,a,b)
'  28 IDirect3DDevice2_MultiplyTransform(p,a,b)              (p)->lpVtbl->MultiplyTransform(p,a,b)
'  29 IDirect3DDevice2_DrawPrimitive(p,a,b,c,d,e)            (p)->lpVtbl->DrawPrimitive(p,a,b,c,d,e)
'  30 IDirect3DDevice2_DrawIndexedPrimitive(p,a,b,c,d,e,f,g) (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f,g)
'  31 IDirect3DDevice2_SetClipStatus(p,a)                    (p)->lpVtbl->SetClipStatus(p,a)
'  32 IDirect3DDevice2_GetClipStatus(p,a)                    (p)->lpVtbl->GetClipStatus(p,a)

' ****************************************************************************************
function d3dDevice2Prototype() as hresult  
  FatalError("D3DDevice2::#%i Function not implemented",D3DDEVICE2PROTOID)  
  return DDERR_UNSUPPORTED
  
  
  asm
    .balign 32
    _d3dDevice2ProtoTable_:  
    #macro ProtoNum(X)
    mov dword ptr [D3DDEVICE2PROTOID],X
    jmp d3dDevice2Prototype
    .balign 32
    #endmacro
    ProtoNum(0)
    ProtoNum(1)
    ProtoNum(2)
    ProtoNum(3)
    ProtoNum(4)
    ProtoNum(5)
    ProtoNum(6)
    ProtoNum(7)
    ProtoNum(8)
    ProtoNum(9)
    ProtoNum(10)
    ProtoNum(11)
    ProtoNum(12)
    ProtoNum(13)
    ProtoNum(14)
    ProtoNum(15)
    ProtoNum(16)
    ProtoNum(17)
    ProtoNum(18)
    ProtoNum(19)
    ProtoNum(20)
    ProtoNum(21)
    ProtoNum(22)
    ProtoNum(23)
    ProtoNum(24)
    ProtoNum(25)
    ProtoNum(26)
    ProtoNum(27)
    ProtoNum(28)
    ProtoNum(29)
    ProtoNum(30)
    ProtoNum(31)
    ProtoNum(32)
    ProtoNum(33)
  end asm  
  
end function
#ifdef Render_OpenGL
' ****************************************************************************************
UndefAll()
#define P1 pTHIS as d3dDevice2Object ptr
function d3dDevice2_2_Release(P1) as hresult
  #ifdef MyDebugD3D
  Cout("IDirect3D2::D3dDevice.Release (2)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8))
  #endif
  
  #ifdef RecordRaces
  mutexlock(rec.pMutex)
  rec.EndRecord()
  mutexunlock(rec.pMutex)
  #endif
  
  for CNT as integer = 0 to ubound(GlTextures)
    if glTexTures(CNT) then
      mt_glDeleteTextures(1,@CNT)
      glTextures(CNT)=0
      check()
    end if
  next CNT
  ogl.LastBind = 0 : ogl.LastSurface=0 : CURRDEVICE = 0
  Delete pTHIS
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pTHIS     as d3dDevice2Object ptr
#define P2 pViewPort as d3dViewPort2Object ptr
function d3dDevice2_6_AddViewport(P1,P2) as hresult
  #ifdef MyDebugD3D
  Cout("IDirect3D2::D3dDevice.AddViewport (6)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8)+ _
  "  pViewPort: "+hexptr(pViewPort))
  #endif
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT)
  elseif pViewPort=NULL orelse pViewPort->Interface <> itd3dViewPort2 then
    ddrawerror(DDERR_INVALIDPARAMS)
  end if
  #ifdef MyDebugErr
  if pThis->ViewPort then
    lCout("<<<< WARNING >>>> Second Viewport Added!!!")
  end if
  #endif
  pTHIS->Viewport = pViewPort: Enabled3D = 1
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pTHIS     as d3dDevice2Object ptr
#define P2 pViewPort as d3dViewPort2Object ptr
function d3dDevice2_7_DeleteViewport(P1,P2) as hresult
  #ifdef MyDebugD3D
  Cout("IDirect3D2::D3dDevice.DeleteViewport (7)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8)+ _
  "  pViewPort: "+hexptr(pViewPort))
  #endif
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT)
  elseif pViewPort=NULL orelse pViewPort->Interface <> itd3dViewPort2 then
    ddrawerror(DDERR_INVALIDPARAMS)
  end if
  if pTHIS->Viewport = pViewPort then pTHIS->ViewPort=NULL: Enabled3D = 0
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pTHIS as d3dDevice2Object ptr
#define P2 pCb   as LPD3DENUMTEXTUREFORMATSCALLBACK
#define P3 lpArg as any ptr
function d3dDevice2_9_EnumTextureFormats(P1,P2,P3) as hresult
  #ifdef MyDebugD3D
  Cout("IDirect3D2::D3dDevice.EnumTextureFormats (9)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8)+ _
  "  pCb: "+hexptr(pCb)+" Arg: "+hex$(lpArg))
  #endif
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT)
  end if
  
  dim as DDSURFACEDESC DESC
  with DESC
    .dwSize = sizeof(DDSURFACEDESC)
    .dwFlags = DDSD_PIXELFORMAT or DDSD_CAPS    
    .ddsCaps.dwCaps = DDSCAPS_TEXTURE 
    .ddpfPixelFormat.dwSize = sizeof(.ddpfPixelFormat)
    with DESC.ddpfPixelFormat
      
      .dwflags = DDPF_RGB or DDPF_PALETTEINDEXED8
      .dwRGBBitCount = 8      
      pCb(@DESC,lpArg)
      
      .dwflags = DDPF_RGB
      .dwRGBBitCount = 8      
      .dwRBitMask        = &h000000E0
      .dwGBitMask        = &h0000001C
      .dwBBitMask        = &h00000003
      .dwRGBAlphaBitMask = &h00000000
      pCb(@DESC,lpArg) 
      
      .dwflags = DDPF_RGB or DDPF_ALPHAPIXELS
      .dwRGBBitCount = 16
      .dwRBitMask        = &h00000F00
      .dwGBitMask        = &h000000F0
      .dwBBitMask        = &h0000000F
      .dwRGBAlphaBitMask = &h0000F000
      pCb(@DESC,lpArg)
            
      .dwflags = DDPF_RGB
      .dwRGBBitCount = 16
      .dwRBitMask        = &b1111100000000000
      .dwGBitMask        = &b0000011111100000
      .dwBBitMask        = &b0000000000011111
      .dwRGBAlphaBitMask = &b0000000000000000      
      pCb(@DESC,lpArg)  
      
      .dwflags = DDPF_RGB or DDPF_ALPHAPIXELS
      .dwRGBBitCount = 16
      .dwRBitMask        = &h00007C00
      .dwGBitMask        = &h000003E0
      .dwBBitMask        = &h0000001F
      .dwRGBAlphaBitMask = &h00008000
      pCb(@DESC,lpArg)
      
    end with    
  end with
  
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pTHIS as d3dDevice2Object ptr
function d3dDevice2_10_BeginScene(P1) as hresult
  #ifdef MyDebugD3D
  Cout("IDirect3D2::D3dDevice.BeginScene (10)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8))  
  if pTHIS->InScene then
    lCout("Warning Scene already started!")
  end if
  #endif
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT)
  end if    
  ogl.PrimCount = 0
  #if 0
    for CNT as integer = 0 to ubound(iSceneFuncs)
      iSceneFuncs(CNT) = 0: zSceneFuncs(CNT) = ""
    next CNT  
  #endif  
  'mt_glFlush()
  mutexlock(RenderMutex)
  mt_SetCurrent(False)  
  if wglMakeCurrent(ogl.hDC,ogl.Ctx)=0 then
    printf(!"Failed to set current %s:%i\n",__FUNCTION__,__LINE__)
  end if  
  pTHIS->InScene = true: ogl.InScene = true 
  #ifdef DebugDeviceTime
    dim as zstring*256 sText
    sprintf(sText,!"Begin:%2.3g(%i)  ",(timer-DeviceTime)*1000,GetCurrentThreadID())
    printf(sText):cout(sText):DeviceTime = timer
    DeviceTime = timer
  #endif
  
  #ifdef RecordRaces
  rec.BeginRecord(ogl.PortX,ogl.PortY)
  #endif
  
  TestRot = (TestRot+1) and 3
  
  #if 0
  dim as zstring ptr zBlend(...) = {@"GL_ZERO",@"GL_ONE",@"GL_SRC_COLOR",@"GL_ONE_MINUS_SRC_COLOR", _
  @"GL_SRC_ALPHA",@"GL_ONE_MINUS_SRC_ALPHA",@"GL_DST_ALPHA",@"GL_ONE_MINUS_DST_ALPHA", _
  @"GL_DST_COLOR",@"GL_ONE_MINUS_DST_COLOR",@"GL_SRC_ALPHA_SATURATE",@"GL_CONSTANT_COLOR", _
  @"GL_ONE_MINUS_CONSTANT_COLOR",@"GL_CONSTANT_ALPHA",@"GL_ONE_MINUS_CONSTANT_ALPHA" }
  dim as integer iBlend(...) = {0,1,&h300,&h301,&h302, _
  &h303,&h304,&h305,&h306,&h307,&h308,&h8001,&h8002,&h8003,&h8004 }
  if BlendB=-1 then 
    BlendB=0:printf(!"%s(%x),%s(%x)\n",zBlend(BlendA),iBlend(BlendA),zBlend(BlendB),iBLend(BlendB))
  end if
  BlendSrc = iBlend(BlendA): BlendTgt = iBlend(BlendB)
  if (getkeystate(VK_Q) shr 15) then
    while (getkeystate(VK_Q) shr 15): sleepex 1,1: wend    
    BlendB += 1: if BlendB = GL_SRC_ALPHA_SATURATE then BlendB += 1
    if BlendB > ubound(iBlend) then 
      BlendB=0: BlendA += 1
      if BlendA > ubound(iBlend) then BlendA = 0
    end if
    printf(!"%s(%x),%s(%x)\n",zBlend(BlendA),iBlend(BlendA),zBlend(BlendB),iBLend(BlendB))
  end if
  if (getkeystate(VK_A) shr 15) then
    while (getkeystate(VK_A) shr 15): sleepex 1,1: wend
    BlendB -= 1
    if BlendB < 0 then 
      BlendB=ubound(iBlend): BlendA -= 1
      if BlendA < 0 then BlendA = ubound(iBlend)
    end if
    printf(!"%s(%x),%s(%x)\n",zBlend(BlendA),iBlend(BlendA),zBlend(BlendB),iBLend(BlendB))
  end if  
  #endif
  
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pTHIS as d3dDevice2Object ptr
function d3dDevice2_11_EndScene(P1) as hresult
  #ifdef MyDebugD3D
    Cout("IDirect3D2::D3dDevice.EndScene (11)" + chr$(13,10) + _
    " >> THIS: "+hex$(cast(uinteger,pTHIS),8))  
    if pTHIS->InScene=0 then
      lCout("Warning NO Scene started!")
    end if
  #endif
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT)
  end if  
  'mt_glFlush()  
  'CURRDEVICE = null
  if wglMakeCurrent(null,null) = 0 then
    printf(!"Failed to release current %s:%i\n",__FUNCTION__,__LINE__)
  end if  
  mt_SetCurrent(True)
  
  #ifdef DebugDeviceTime
    dim as zstring*256 sText
    sprintf(sText,!"End:%2.3g(%i)  ",(timer-DeviceTime)*1000,GetCurrentThreadID())
    printf(sText):cout(sText):DeviceTime = timer
    DeviceTime = timer
  #endif
  
  #ifdef RecordRaces
  mutexlock(rec.pMutex)
  rec.FrameRecord()
  mutexunlock(rec.pMutex)
  #endif
  
  mutexunlock(RenderMutex)
  pTHIS->InScene = false: ogl.InScene = false
  'printf(!"Triangles=%i\n",ogl.PrimCount)
  ogl.PrimMax=ogl.PrimCount:ogl.PrimCount=0
  #if 0
    for CNT as integer = 0 to ubound(iSceneFuncs)
      if iSceneFuncs(CNT) then
        printf(!"x%i %s",iSceneFuncs(CNT),zSceneFuncs(CNT))
        zSceneFuncs(CNT)="":iSceneFuncs(CNT)=0
      end if
    next CNT
    printf(!"-------------------------------------------")
  #endif
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pTHIS     as d3dDevice2Object ptr
#define P2 pViewPort as d3dViewPort2Object ptr
function d3dDevice2_13_SetCurrentViewport(P1,P2) as hresult
  #ifdef MyDebugD3D
  Cout("IDirect3D2::D3dDevice.SetCurrentViewport (13)" + chr$(13,10) + _
  " >> THIS: "+hex$(cast(uinteger,pTHIS),8)+ _
  "  pViewPort: "+hexptr(pViewPort))
  #endif
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT)
  elseif pViewPort=NULL orelse pViewPort->Interface <> itd3dViewPort2 then
    ddrawerror(DDERR_INVALIDPARAMS)
  end if
  CURRDEVICE = pTHIS
  'TODO: need something to actually activate it? probabily when
  '2 viewports are being used i will need to do that...
  return DD_OK
end function
' ****************************************************************************************
#if 1 'def MyDebugD3D
function GetRenderStateType(dwType as dword) as string
  select case dwType
  case D3DRENDERSTATE_ANTIALIAS                 :return "ANTIALIAS"
	case D3DRENDERSTATE_TEXTUREPERSPECTIVE        :return "TEXTUREPERSPECTIVE"
	case D3DRENDERSTATE_ZENABLE                   :return "ZENABLE"
	case D3DRENDERSTATE_FILLMODE                  :return "FILLMODE"
	case D3DRENDERSTATE_SHADEMODE                 :return "SHADEMODE"
	case D3DRENDERSTATE_LINEPATTERN               :return "LINEPATTERN"
	case D3DRENDERSTATE_ZWRITEENABLE              :return "ZWRITEENABLE"
	case D3DRENDERSTATE_ALPHATESTENABLE           :return "ALPHATESTENABLE"
	case D3DRENDERSTATE_LASTPIXEL                 :return "LASTPIXEL"
	case D3DRENDERSTATE_SRCBLEND                  :return "SRCBLEND"
	case D3DRENDERSTATE_DESTBLEND                 :return "DESTBLEND"
	case D3DRENDERSTATE_CULLMODE                  :return "CULLMODE"
	case D3DRENDERSTATE_ZFUNC                     :return "ZFUNC"
	case D3DRENDERSTATE_ALPHAREF                  :return "ALPHAREF"
	case D3DRENDERSTATE_ALPHAFUNC                 :return "ALPHAFUNC"
	case D3DRENDERSTATE_DITHERENABLE              :return "DITHERENABLE"
	case D3DRENDERSTATE_ALPHABLENDENABLE          :return "ALPHABLENDENABLE"
	case D3DRENDERSTATE_FOGENABLE                 :return "FOGENABLE"
	case D3DRENDERSTATE_SPECULARENABLE            :return "SPECULARENABLE"
  case D3DRENDERSTATE_ZVISIBLE                  :return "ZVISIBLE"
	case D3DRENDERSTATE_STIPPLEDALPHA             :return "STIPPLEDALPHA"
	case D3DRENDERSTATE_FOGCOLOR                  :return "FOGCOLOR"
	case D3DRENDERSTATE_FOGTABLEMODE              :return "FOGTABLEMODE"
	case D3DRENDERSTATE_FOGSTART                  :return "FOGSTART"
	case D3DRENDERSTATE_FOGEND                    :return "FOGEND"
	case D3DRENDERSTATE_FOGDENSITY                :return "FOGDENSITY"
	case D3DRENDERSTATE_EDGEANTIALIAS             :return "EDGEANTIALIAS"
	case D3DRENDERSTATE_COLORKEYENABLE            :return "COLORKEYENABLE"
	case D3DRENDERSTATE_ZBIAS                     :return "ZBIAS"
	case D3DRENDERSTATE_RANGEFOGENABLE            :return "RANGEFOGENABLE"
	case D3DRENDERSTATE_STENCILENABLE             :return "STENCILENABLE"
	case D3DRENDERSTATE_STENCILFAIL               :return "STENCILFAIL"
	case D3DRENDERSTATE_STENCILZFAIL              :return "STENCILZFAIL"
	case D3DRENDERSTATE_STENCILPASS               :return "STENCILPASS"
	case D3DRENDERSTATE_STENCILFUNC               :return "STENCILFUNC"
	case D3DRENDERSTATE_STENCILREF                :return "STENCILREF"
	case D3DRENDERSTATE_STENCILMASK               :return "STENCILMASK"
	case D3DRENDERSTATE_STENCILWRITEMASK          :return "STENCILWRITEMASK"
	case D3DRENDERSTATE_TEXTUREFACTOR             :return "TEXTUREFACTOR"
	case D3DRENDERSTATE_WRAP0                     :return "WRAP0"
	case D3DRENDERSTATE_WRAP1                     :return "WRAP1"
	case D3DRENDERSTATE_WRAP2                     :return "WRAP2"
	case D3DRENDERSTATE_WRAP3                     :return "WRAP3"
	case D3DRENDERSTATE_WRAP4                     :return "WRAP4"
	case D3DRENDERSTATE_WRAP5                     :return "WRAP5"
	case D3DRENDERSTATE_WRAP6                     :return "WRAP6"
	case D3DRENDERSTATE_WRAP7                     :return "WRAP7"
	case D3DRENDERSTATE_CLIPPING                  :return "CLIPPING"
	case D3DRENDERSTATE_LIGHTING                  :return "LIGHTING"
	case D3DRENDERSTATE_EXTENTS                   :return "EXTENTS"
	case D3DRENDERSTATE_AMBIENT                   :return "AMBIENT"
	case D3DRENDERSTATE_FOGVERTEXMODE             :return "FOGVERTEXMODE"
	case D3DRENDERSTATE_COLORVERTEX               :return "COLORVERTEX"
	case D3DRENDERSTATE_LOCALVIEWER               :return "LOCALVIEWER"
	case D3DRENDERSTATE_NORMALIZENORMALS          :return "NORMALIZENORMALS"
	case D3DRENDERSTATE_COLORKEYBLENDENABLE       :return "COLORKEYBLENDENABLE"
	case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE     :return "DIFFUSEMATERIALSOURCE"
	case D3DRENDERSTATE_SPECULARMATERIALSOURCE    :return "SPECULARMATERIALSOURCE"
	case D3DRENDERSTATE_AMBIENTMATERIALSOURCE     :return "AMBIENTMATERIALSOURCE"
	case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE    :return "EMISSIVEMATERIALSOURCE"
	case D3DRENDERSTATE_VERTEXBLEND               :return "VERTEXBLEND"
	case D3DRENDERSTATE_CLIPPLANEENABLE           :return "CLIPPLANEENABLE"
	case D3DRENDERSTATE_TEXTUREHANDLE             :return "TEXTUREHANDLE"
	case D3DRENDERSTATE_TEXTUREADDRESS            :return "TEXTUREADDRESS"
	case D3DRENDERSTATE_WRAPU                     :return "WRAPU"
	case D3DRENDERSTATE_WRAPV                     :return "WRAPV"
	case D3DRENDERSTATE_MONOENABLE                :return "MONOENABLE"
	case D3DRENDERSTATE_ROP2                      :return "ROP2"
	case D3DRENDERSTATE_PLANEMASK                 :return "PLANEMASK"
	case D3DRENDERSTATE_TEXTUREMAG                :return "TEXTUREMAG"
	case D3DRENDERSTATE_TEXTUREMIN                :return "TEXTUREMIN"
	case D3DRENDERSTATE_TEXTUREMAPBLEND           :return "TEXTUREMAPBLEND"
	case D3DRENDERSTATE_SUBPIXEL                  :return "SUBPIXEL"
	case D3DRENDERSTATE_SUBPIXELX                 :return "SUBPIXELX"
	case D3DRENDERSTATE_STIPPLEENABLE             :return "STIPPLEENABLE"
	case D3DRENDERSTATE_BORDERCOLOR               :return "BORDERCOLOR"
	case D3DRENDERSTATE_TEXTUREADDRESSU           :return "TEXTUREADDRESSU"
	case D3DRENDERSTATE_TEXTUREADDRESSV           :return "TEXTUREADDRESSV"
	case D3DRENDERSTATE_MIPMAPLODBIAS             :return "MIPMAPLODBIAS"
	case D3DRENDERSTATE_ANISOTROPY                :return "ANISOTROPY"
	case D3DRENDERSTATE_FLUSHBATCH                :return "FLUSHBATCH"
	case D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT:return "TRANSLUCENTSORTINDEPENDENT"
	case D3DRENDERSTATE_STIPPLEPATTERN00          :return "STIPPLEPATTERN00"
	case D3DRENDERSTATE_STIPPLEPATTERN01          :return "STIPPLEPATTERN01"
	case D3DRENDERSTATE_STIPPLEPATTERN02          :return "STIPPLEPATTERN02"
	case D3DRENDERSTATE_STIPPLEPATTERN03          :return "STIPPLEPATTERN03"
	case D3DRENDERSTATE_STIPPLEPATTERN04          :return "STIPPLEPATTERN04"
	case D3DRENDERSTATE_STIPPLEPATTERN05          :return "STIPPLEPATTERN05"
	case D3DRENDERSTATE_STIPPLEPATTERN06          :return "STIPPLEPATTERN06"
	case D3DRENDERSTATE_STIPPLEPATTERN07          :return "STIPPLEPATTERN07"
	case D3DRENDERSTATE_STIPPLEPATTERN08          :return "STIPPLEPATTERN08"
	case D3DRENDERSTATE_STIPPLEPATTERN09          :return "STIPPLEPATTERN09"
	case D3DRENDERSTATE_STIPPLEPATTERN10          :return "STIPPLEPATTERN10"
	case D3DRENDERSTATE_STIPPLEPATTERN11          :return "STIPPLEPATTERN11"
	case D3DRENDERSTATE_STIPPLEPATTERN12          :return "STIPPLEPATTERN12"
	case D3DRENDERSTATE_STIPPLEPATTERN13          :return "STIPPLEPATTERN13"
	case D3DRENDERSTATE_STIPPLEPATTERN14          :return "STIPPLEPATTERN14"
	case D3DRENDERSTATE_STIPPLEPATTERN15          :return "STIPPLEPATTERN15"
	case D3DRENDERSTATE_STIPPLEPATTERN16          :return "STIPPLEPATTERN16"
	case D3DRENDERSTATE_STIPPLEPATTERN17          :return "STIPPLEPATTERN17"
	case D3DRENDERSTATE_STIPPLEPATTERN18          :return "STIPPLEPATTERN18"
	case D3DRENDERSTATE_STIPPLEPATTERN19          :return "STIPPLEPATTERN19"
	case D3DRENDERSTATE_STIPPLEPATTERN20          :return "STIPPLEPATTERN20"
	case D3DRENDERSTATE_STIPPLEPATTERN21          :return "STIPPLEPATTERN21"
	case D3DRENDERSTATE_STIPPLEPATTERN22          :return "STIPPLEPATTERN22"
	case D3DRENDERSTATE_STIPPLEPATTERN23          :return "STIPPLEPATTERN23"
	case D3DRENDERSTATE_STIPPLEPATTERN24          :return "STIPPLEPATTERN24"
	case D3DRENDERSTATE_STIPPLEPATTERN25          :return "STIPPLEPATTERN25"
	case D3DRENDERSTATE_STIPPLEPATTERN26          :return "STIPPLEPATTERN26"
	case D3DRENDERSTATE_STIPPLEPATTERN27          :return "STIPPLEPATTERN27"
	case D3DRENDERSTATE_STIPPLEPATTERN28          :return "STIPPLEPATTERN28"
	case D3DRENDERSTATE_STIPPLEPATTERN29          :return "STIPPLEPATTERN29"
	case D3DRENDERSTATE_STIPPLEPATTERN30          :return "STIPPLEPATTERN30"
	case D3DRENDERSTATE_STIPPLEPATTERN31          :return "STIPPLEPATTERN31"
	case D3DRENDERSTATE_FOGTABLESTART             :return "FOGTABLESTART"
	case D3DRENDERSTATE_FOGTABLEEND               :return "FOGTABLEEND"
	case D3DRENDERSTATE_FOGTABLEDENSITY           :return "FOGTABLEDENSITY"  
  end select
  return "unkown 0x" & hex$(dwtype)
end function
#endif
' ****************************************************************************************
UndefAll()
#define P1 pTHIS   as d3dDevice2Object ptr
#define P2 dwType  as dword
#define P3 dwValue as dword
function d3dDevice2_23_SetRenderState(P1,P2,P3) as hresult  
  #ifdef MyDebugD3D
    dim as string sValue = "unknown"
    #define MyDebugD3DSetValue(ss) sValue = ss
    Cout("IDirect3D2::D3dDevice.SetRenderState (23)" + "  THIS: "+hexptr(pTHIS))  
  #else
    #define MyDebugD3DSetValue(ss)
    'dim as string sValue = "unknown"
    '#define MyDebugD3DSetValue(ss) sValue = ss
  #endif
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT) 
  end if
  select case as const dwType
  case D3DRENDERSTATE_COLORKEYENABLE
    if dwValue then
      MyDebugD3DSetValue("True")
      pTHIS->ColorKeyOn = true   
      end
    else
      MyDebugD3DSetValue("False")
      pTHIS->ColorKeyOn = false
    end if
  case D3DRENDERSTATE_FLUSHBATCH
    MyDebugD3DSetValue("Flush")    
    'mt_glFlush()
  case D3DRENDERSTATE_TEXTUREHANDLE
    dim as integer iTex
    dim as ddSurfaceObject ptr pTex
    if dwValue=null then
      MyDebugD3DSetValue("Empty")
      iTex=0
    else      
      MyDebugD3DSetValue("Texture")
      pTex = cast(any ptr,dwValue)
      pThis->SelTex = pTex
      with *pTex
        if .Interface <> itSurface then
          ddrawError(DDERR_INVALIDPARAMS)
        end if
        if .ID > 0 then
          iTex = .ID
        else
          #ifdef MyDebugD3D
          lcout("Tried to bind bad texture " & __LINE__)
          #endif
        end if
      end with
    end if  

    if iTex andalso (pTex->NeedUpdate<>0) then ' or QAlpha<>(pTex->QAlpha)) then
      pTex->QAlpha = QAlpha
      pTex->NeedUpdate =0: ogl.LastTex = iTex
      if pTex->bpp=8 then
        var pPal = pTex->Pal
        if pPal = 0 then
          #ifdef MyDebugErr
          lcout("NO PAL??? O_O")
          #endif
        else
          mt_glUpdateTexture8(pTex,pTex->Wid,pTex->Hei,cast(any ptr,pTex->fbImage+1),@(pPal->Pal(0)))
        end if
      else
        mt_glUpdateTexture16(pTex,pTex->Wid,pTex->Hei,cast(any ptr,pTex->fbImage+1))
      end if
    else
      mt_glBindTexture(GL_TEXTURE_2D,pTex)
    end if
    
    ogl.IsDust = 0
    if iTex then
      select case pTex->Hash    
      case &h1AA802253AE45575ull,&h34B1F4E1373FA3EEull, _ 'Australia/Canada     
      &h393CA73D0B73A844ull,&h44783F77A998E5ACull,      _ 'Switzerland/Sweden   
      &h71AA226830B0C4D9ull,&hBAA8932F6702948Eull,      _ 'Egypt/USA            
      &h9F680EE2B9C5A920ull,&hA614B1794E5A7B67ull  ,    _ 'Finland/GreatBritain 
      &hC6F49F6A12801FA7ull, _           'Brazil/Africa/Indonesia/Italy/Russia 
      &hCE277406CECA857Aull,&hD1FBB8E73BEA1EAFull         'China/Japan          
        ogl.IsDust = 1
      end select
    end if
    
    #ifdef RecordRaces
    if iTex >= 0 then
      var iTexID = rec.iTexAdded(iTex)
      rec_PutTexture(iTexID)          
    end if
    #endif
    
  case D3DRENDERSTATE_ZENABLE
    select case dwValue
    case D3DZB_FALSE
      MyDebugD3DSetValue("False")
      mt_glDisable(GL_DEPTH_TEST)
    case D3DZB_TRUE,1,-1
      MyDebugD3DSetValue("True")
      mt_glEnable(GL_DEPTH_TEST)
    case else
      #ifdef MyDebugD3D
      lcout("Not Supported value")
      #endif
    end select
  case D3DRENDERSTATE_STIPPLEENABLE
    if dwValue then
      MyDebugD3DSetValue("True")
      mt_glEnable(GL_POLYGON_STIPPLE)
    else
      MyDebugD3DSetValue("False")
      mt_glDisable(GL_POLYGON_STIPPLE)
    end if
  case D3DRENDERSTATE_DITHERENABLE
    if dwValue then
      MyDebugD3DSetValue("True")
      mt_glEnable(GL_DITHER)
    else
      MyDebugD3DSetValue("False")
      mt_glDisable(GL_DITHER)
    end if
  case D3DRENDERSTATE_ALPHABLENDENABLE
    if dwValue then
      MyDebugD3DSetValue("True")
      mt_glEnable(GL_ALPHA_TEST)
      mt_glEnable(GL_BLEND)
      'mt_glDisable(GL_BLEND)
      pThis->BlendON = true  
      ogl.Blend = true      
    else
      MyDebugD3DSetValue("False")
      mt_glDisable(GL_BLEND)
      mt_glDisable(GL_ALPHA_TEST)
      pThis->BlendON = false
      ogl.Blend = false
      #ifdef RecordRaces
        mutexlock(rec.pMutex)
        rec_PutBlend(RecNoBlend)
        mutexunlock(rec.pMutex)
      #endif
    end if
  case D3DRENDERSTATE_FOGENABLE
    if dwValue then
      MyDebugD3DSetValue("True")      
      if pThis->FogOn=0 then
        mt_glEnable(GL_FOG)               
        pThis->FogOn=true:ogl.Fog=True
      end if
    else
      MyDebugD3DSetValue("False")      
      if pThis->FogOn then
        mt_glDisable(GL_FOG)        
        pThis->FogOn=false:ogl.Fog=false
      end if
    end if
  case D3DRENDERSTATE_FOGTABLEMODE
    dim as integer iFog = -1
    select case dwValue
    case D3DFOG_NONE  : iFog = 0        : MyDebugD3DSetValue("No Fog")
    case D3DFOG_EXP   : iFog = GL_EXP   : MyDebugD3DSetValue("Exp Fog")
    case D3DFOG_EXP2  : iFog = GL_EXP2  : MyDebugD3DSetValue("ExpSqr Fog")
    case D3DFOG_LINEAR: iFog = GL_LINEAR: MyDebugD3DSetValue("Linear Fog")
    end select
    if iFog = 0 then      
      mt_glFogi(GL_FOG_MODE,GL_LINEAR)
      mt_glFogi(GL_FOG_COORD_SRC,GL_FOG_COORD)
      printf(!"especial fog mode?\n")
    else
      'mt_glEnable(GL_FOG)
      mt_glFogi(GL_FOG_MODE,iFog)
      printf(!"enabled fog mode %i!!\n",dwValue)
      system
    end if
  case D3DRENDERSTATE_ZWRITEENABLE
    if dwValue then
      MyDebugD3DSetValue("True")
      mt_glEnable(GL_DEPTH_WRITEMASK)
    else
      MyDebugD3DSetValue("False")
      mt_glDisable(GL_DEPTH_WRITEMASK)
    end if
  case D3DRENDERSTATE_SHADEMODE
    if dwValue = D3DSHADE_FLAT then
      MyDebugD3DSetValue("Flat")
      mt_glShadeModel(GL_FLAT)
    else 'D3DSHADE_GOURAD
      MyDebugD3DSetValue("Gourad")
      mt_glShadeModel(GL_SMOOTH) 'TODO: what else is needed?
    end if
  case D3DRENDERSTATE_TEXTUREPERSPECTIVE
    if dwValue then      
      MyDebugD3DSetValue("ON")
      mt_glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST)
    else
      MyDebugD3DSetValue("OFF")
      mt_glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_FASTEST)      
    end if
  case D3DRENDERSTATE_STIPPLEDALPHA
    if dwValue then      
      MyDebugD3DSetValue("ON (Unsupported?)")
      printf(!"Stippled alpha enabled!\n")
      system
    else 'TODO: emulate this?
      MyDebugD3DSetValue("OFF")      
    end if
  case D3DRENDERSTATE_SRCBLEND
    select case dwValue
    case D3DBLEND_ZERO
      MyDebugD3DSetValue("ZERO")
      pThis->SrcBlend = GL_ZERO
    case D3DBLEND_ONE            
      MyDebugD3DSetValue("ONE")
      pThis->SrcBlend = GL_ONE
    case D3DBLEND_SRCCOLOR     
      MyDebugD3DSetValue("SRCCOLOR")
      pThis->SrcBlend = GL_SRC_COLOR
    case D3DBLEND_INVSRCCOLOR    
      MyDebugD3DSetValue("INVSRCCOLOR")
      pThis->SrcBlend = GL_ONE_MINUS_SRC_COLOR
    case D3DBLEND_SRCALPHA       
      MyDebugD3DSetValue("SRCALPHA")
      pThis->SrcBlend = GL_SRC_ALPHA
    case D3DBLEND_INVSRCALPHA    
      MyDebugD3DSetValue("INVSRCALPHA")
      pThis->SrcBlend = GL_ONE_MINUS_SRC_ALPHA
    case D3DBLEND_DESTALPHA      
      MyDebugD3DSetValue("DESTALPHA")
      pThis->SrcBlend = GL_DST_ALPHA
    case D3DBLEND_INVDESTALPHA   
      MyDebugD3DSetValue("INVDESTALPHA")
      pThis->SrcBlend = GL_ONE_MINUS_DST_ALPHA
    case D3DBLEND_DESTCOLOR      
      MyDebugD3DSetValue("DESTCOLOR")
      pThis->SrcBlend = GL_DST_COLOR
    case D3DBLEND_INVDESTCOLOR   
      MyDebugD3DSetValue("INVDESTCOLOR")
      pThis->SrcBlend = GL_ONE_MINUS_DST_COLOR
    case D3DBLEND_SRCALPHASAT    
      MyDebugD3DSetValue("SRCALPHASAT")
      pThis->SrcBlend = GL_SRC_ALPHA_SATURATE
    case D3DBLEND_BOTHSRCALPHA   
      MyDebugD3DSetValue("BOTHSRCALPHA")
      pThis->SrcBlend = GL_SRC_ALPHA
      pThis->TgtBlend = GL_SRC_ALPHA
    case D3DBLEND_BOTHINVSRCALPHA
      MyDebugD3DSetValue("BOTHINVSRCALPHA")
      pThis->SrcBlend = GL_ONE_MINUS_SRC_ALPHA
      pThis->TgtBlend = GL_ONE_MINUS_SRC_ALPHA
    end select    
    if pThis->SrcBlend = GL_ZERO then
      QALPHA = &hFF000000FF000000ull
      #ifdef RecordRaces
        mutexlock(rec.pMutex)
        rec_PutBlend(RecBlendAdd)
        mutexunlock(rec.pMutex)
      #endif
    else              
      QALPHA = &hF0000000F0000000ull
      #ifdef RecordRaces
        mutexlock(rec.pMutex)
        rec_PutBlend(RecBlendAlpha)
        mutexunlock(rec.pMutex)
      #endif
    end if
    #if 1
      mt_glBlendFunc(pThis->SrcBlend,pThis->TgtBlend)
    #else
      mt_glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
    #endif
  case D3DRENDERSTATE_DESTBLEND
    select case dwValue
    case D3DBLEND_ZERO
      MyDebugD3DSetValue("ZERO")
      pThis->TgtBlend = GL_ZERO
    case D3DBLEND_ONE            
      MyDebugD3DSetValue("ONE")
      pThis->TgtBlend = GL_ONE
    case D3DBLEND_SRCCOLOR     
      MyDebugD3DSetValue("SRCCOLOR")
      pThis->TgtBlend = GL_SRC_COLOR
    case D3DBLEND_INVSRCCOLOR    
      MyDebugD3DSetValue("INVSRCCOLOR")
      pThis->TgtBlend = GL_ONE_MINUS_SRC_COLOR
    case D3DBLEND_SRCALPHA       
      MyDebugD3DSetValue("SRCALPHA")
      pThis->TgtBlend = GL_SRC_ALPHA
    case D3DBLEND_INVSRCALPHA    
      MyDebugD3DSetValue("INVSRCALPHA")
      pThis->TgtBlend = GL_ONE_MINUS_SRC_ALPHA
    case D3DBLEND_DESTALPHA      
      MyDebugD3DSetValue("DESTALPHA")
      pThis->TgtBlend = GL_DST_ALPHA
    case D3DBLEND_INVDESTALPHA   
      MyDebugD3DSetValue("INVDESTALPHA")
      pThis->TgtBlend = GL_ONE_MINUS_DST_ALPHA
    case D3DBLEND_DESTCOLOR      
      MyDebugD3DSetValue("DESTCOLOR")
      pThis->TgtBlend = GL_DST_COLOR
    case D3DBLEND_INVDESTCOLOR   
      MyDebugD3DSetValue("INVDESTCOLOR")
      pThis->TgtBlend = GL_ONE_MINUS_DST_COLOR
    case D3DBLEND_SRCALPHASAT    
      MyDebugD3DSetValue("SRCALPHASAT")
      pThis->TgtBlend = GL_SRC_ALPHA_SATURATE
    case D3DBLEND_BOTHSRCALPHA   
      MyDebugD3DSetValue("BOTHSRCALPHA")
      pThis->SrcBlend = GL_SRC_ALPHA
      pThis->TgtBlend = GL_SRC_ALPHA
    case D3DBLEND_BOTHINVSRCALPHA
      MyDebugD3DSetValue("BOTHINVSRCALPHA")
      pThis->SrcBlend = GL_ONE_MINUS_SRC_ALPHA
      pThis->TgtBlend = GL_ONE_MINUS_SRC_ALPHA
    end select
    if pThis->SrcBlend = GL_ONE then
      QALPHA = &hFF000000FF000000ull
      #ifdef RecordRaces
        mutexlock(rec.pMutex)
        rec_PutBlend(RecBlendAdd)
        mutexunlock(rec.pMutex)
      #endif
    else              
      QALPHA = &hF0000000F0000000ull
      #ifdef RecordRaces
        mutexlock(rec.pMutex)
        rec_PutBlend(RecBlendAlpha)
        mutexunlock(rec.pMutex)
      #endif
    end if
    #if 1
      mt_glBlendFunc(pThis->SrcBlend,pThis->TgtBlend)
    #else
      mt_glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
    #endif
  case D3DRENDERSTATE_TEXTUREMAPBLEND
    dim as integer iMode
    'dim as zstring*256 sValue    
    '#define MyDebugD3DSetValue2(ss) sValue = ss    
    select case dwValue
    case D3DTBLEND_DECAL         :iMode=GL_DECAL   :MyDebugD3DSetValue("Decal")
    case D3DTBLEND_DECALALPHA    :iMode=GL_DECAL   :MyDebugD3DSetValue("DecalAlpha")
    case D3DTBLEND_DECALMASK     :iMode=GL_DECAL   :MyDebugD3DSetValue("DecalMask")
    case D3DTBLEND_MODULATE      :iMode=GL_MODULATE:MyDebugD3DSetValue("Modulate")
    case D3DTBLEND_MODULATEALPHA :iMode=GL_MODULATE:MyDebugD3DSetValue("ModulateAlpha")
    case D3DTBLEND_MODULATEMASK  :iMode=GL_MODULATE:MyDebugD3DSetValue("ModulateMask")
    case D3DTBLEND_COPY          :iMode=GL_REPLACE :MyDebugD3DSetValue("Copy")
    end select    
    'iMode=GL_COMBINE':  printf(!"%s\n",sValue)
    'TODO: ALPHA/MASK what else is needed?
    'TODO: COPY is correct as REPLACE?
    mt_glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,iMode)
  case D3DRENDERSTATE_TEXTUREMIN
    dim as integer iType
    select case dwValue
    case D3DFILTER_NEAREST         :iType=GL_NEAREST               :MyDebugD3DSetValue("Nearest")
    case D3DFILTER_LINEAR          :iType=GL_LINEAR                :MyDebugD3DSetValue("Linear")
    case D3DFILTER_MIPNEAREST      :iType=GL_NEAREST_MIPMAP_NEAREST:MyDebugD3DSetValue("Nearest_Nearest")
    case D3DFILTER_MIPLINEAR       :iType=GL_NEAREST_MIPMAP_LINEAR :MyDebugD3DSetValue("Nearest_Linear")
    case D3DFILTER_LINEARMIPNEAREST:iType=GL_LINEAR_MIPMAP_NEAREST :MyDebugD3DSetValue("Linear_Nearest")
    case D3DFILTER_LINEARMIPLINEAR :iType=GL_LINEAR_MIPMAP_LINEAR  :MyDebugD3DSetValue("Linear_Linear")
    end select
    'mt_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,iType)
    #ifdef ogl_UseMipMap
    mt_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR)
    #else
    mt_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
    #endif
    
  case D3DRENDERSTATE_TEXTUREMAG
    dim as integer iType
    select case dwValue
    case D3DFILTER_NEAREST         :iType=GL_NEAREST               :MyDebugD3DSetValue("Nearest")
    case D3DFILTER_LINEAR          :iType=GL_LINEAR                :MyDebugD3DSetValue("Linear")
    case D3DFILTER_MIPNEAREST      :iType=GL_NEAREST_MIPMAP_NEAREST:MyDebugD3DSetValue("Nearest_Nearest")
    case D3DFILTER_MIPLINEAR       :iType=GL_NEAREST_MIPMAP_LINEAR :MyDebugD3DSetValue("Nearest_Linear")
    case D3DFILTER_LINEARMIPNEAREST:iType=GL_LINEAR_MIPMAP_NEAREST :MyDebugD3DSetValue("Linear_Nearest")
    case D3DFILTER_LINEARMIPLINEAR :iType=GL_LINEAR_MIPMAP_LINEAR  :MyDebugD3DSetValue("Linear_Linear")
    end select
    'if _SCALE_ > 1 then
    '  mt_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,iType)
    'else
    mt_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)    
    'end if
  case D3DRENDERSTATE_FOGCOLOR
    MyDebugD3DSetValue("RGB")
    dim as single fFog(3) = { _
    ((dwValue and &h00FF0000) shr 16) / 255, _
    ((dwValue and &h0000FF00) shr  8) / 255, _
    ((dwValue and &h000000FF) shr  0) / 255, _
    ((dwValue and &hFF000000) shr 24) / 255 }
    ogl.FogR=fFog(0): ogl.FogG=fFog(1): ogl.FogB=fFog(2)
    mt_glFogfv(GL_FOG_COLOR,@fFog(0))
  case else
    #ifdef DebugFatal
    #ifdef MyDebugD3D
      printf(!"not implemented state type: %s\n",GetRenderStateType(dwType))
      messagebox(null,"not implemented state type: "+GetRenderStateType(dwType),"Rally 4",MB_ICONERROR or MB_SYSTEMMODAL)
    #else
      printf(!"not implemented state type: %i\n",dwType)
      messagebox(null,"not implemented state type: " & dwType,"Rally 4",MB_ICONERROR or MB_SYSTEMMODAL)
    #endif
    #endif
    'ddrawerror(DDERR_INVALIDPARAMS)
  end select    
  
  'if dwType = D3DRENDERSTATE_SRCBLEND or dwType = D3DRENDERSTATE_DESTBLEND then
  '  lcout(" >> Type: "+GetRenderStateType(dwType)+ " Value: 0x"+hex$(dwValue)+" ("+sValue+")")
  'end if
  #ifdef MyDebugD3D
  lcout(" >> Type: "+GetRenderStateType(dwType)+ " Value: 0x"+hex$(dwValue)+" ("+sValue+")")
  #endif
  return DD_OK
end function
#endif
' ****************************************************************************************
UndefAll()
#define P1 pTHIS as d3dDevice2Object ptr
#define P2 dwName as dword
#define P3 dwValue as dword
function d3dDevice2_25_SetLightState(P1,P2,P3) as hresult
  return DD_OK
  #ifdef MyDebugD3D
    dim as string sName
    select case dwName
    case D3DLIGHTSTATE_MATERIAL   :sName = "Material"
    case D3DLIGHTSTATE_AMBIENT    :sName = "Ambient"
    case D3DLIGHTSTATE_COLORMODEL :sName = "ColorModel"
    case D3DLIGHTSTATE_FOGMODE    :sName = "FogMode"
    case D3DLIGHTSTATE_FOGSTART   :sName = "FogStart"
    case D3DLIGHTSTATE_FOGEND     :sName = "FogEnd"
    case D3DLIGHTSTATE_FOGDENSITY :sName = "FogDensity"
    case D3DLIGHTSTATE_COLORVERTEX:sName = "ColorVertex"
    case else                     :sName = "#"+hex(dwName)
    end select
    Cout("IDirect3D2::D3dDevice.SetLightState (25) >> "+chr$(13,10) + _
    " >> THIS: "+hex$(cast(uinteger,pTHIS),8)+ "Name: "+sName+"  Value: "+hex(dwValue))   
  #endif
  select case dwName
  case D3DLIGHTSTATE_MATERIAL  
    return DD_OK
    if cast(d3dMaterial2Object ptr,dwValue)->interface <> itD3DMaterial2 then      
      printf(!"Bad Material!\n")
      system
    end if      
    with cast(d3dMaterial2Object ptr,dwValue)->Props
      if .dwsize <> sizeof(D3DMATERIAL) then
        printf !"bad size??? %i\n",.dwsize
        system
      end if
      #define f(t,x) 0 (csng((t shr x) and &hFF)/csng(255))
      #macro MakeRGBm(iName,iOut,iIn)      
        'glMaterialfv(GL_FRONT_AND_BACK,iOut,cast(float ptr,@iIn))
        'glLightfv GL_LIGHT0,iOut,cast(float ptr,@iIn)
        'glColor4fv(cast(float ptr,@iIn))
        scope
          static as D3DCOLORVALUE iName = type(-1,-1,-1)                  
          with iIn          
            if iName.r<>.r or iName.g<>.g or iname.b<>.b then
              iName.r=.r:iName.g=.g:iName.b=.b            
              printf(!"%s %1.4f %1.4f %1.4f %1.4f \n",#iIn,.r,.g,.b,.a)
            end if
          end with
        end scope
      #endmacro      
      MakeRGBm(tD,GL_DIFFUSE,.diffuse)
      MakeRGBm(tA,GL_AMBIENT,.ambient)
      MakeRGBm(tS,GL_SPECULAR,.specular)
      MakeRGBm(tE,GL_EMISSION,.emissive)
      'mt_glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,@.power)
    end with    
  case else
    printf(!"Light state??\n")
    messagebox(null,"Not implemented LightSate " & dwName,"Rally 4",MB_SYSTEMMODAL or MB_ICONERROR)
    ExitProcess(1)
  end select
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT)
  end if    
  return DD_OK
end function
' ****************************************************************************************
UndefAll()
#define P1 pTHIS   as d3dDevice2Object ptr
#define P2 dwType  as dword
#define P3 dwFmt   as dword
#define P4 pVert   as any ptr
#define P5 dwCount as dword
#define P6 dwFlags as dword
function d3dDevice2_29_DrawPrimitive(P1,P2,P3,P4,P5,P6) as hresult
  #ifdef Enable3D
  'D3DTLVERTEX
  #ifdef MyDebugD3D
  #ifdef MyDebugD3DQuick
  dim as string sType,sFmt,sFlags
  scope 'Format to String
    select case dwType
    case D3DPT_POINTLIST     : sType = "Points"
    case D3DPT_LINELIST      : sType = "Lines"
    case D3DPT_LINESTRIP     : sType = "LineStrip"
    case D3DPT_TRIANGLELIST  : sType = "Triangles"
    case D3DPT_TRIANGLESTRIP : sType = "TriangleStrip"
    case D3DPT_TRIANGLEFAN   : sType = "TriangleFan"
    case else                : sType = "#"+hex(dwType)
    end select  
    select case dwFmt
    case D3DVT_VERTEX  : sFmt = "Vertex"
    case D3DVT_LVERTEX : sFmt = "Vert+Light"
    case D3DVT_TLVERTEX: sFmt = "Tex+Vert+Light"
    case else          : sFmt = "#"+hex(dwFmt)
    end select
    var iFlags = dwFlags
    if (iFlags and D3DDP_WAIT)               then iFlags -= D3DDP_WAIT      : sFlags += " Wait"
    if (iFlags and D3DDP_DONOTCLIP)          then iFlags -= D3DDP_DONOTCLIP : sFlags += " NoClip"
    if (iFlags and D3DDP_DONOTUPDATEEXTENTS) then iFlags -= &h00000008      : sFlags += " NoUpExt"
    if (iFlags and D3DDP_DONOTLIGHT)         then iFlags -= D3DDP_DONOTLIGHT: sFlags += " NoLight"
    if iFlags then sFlags += " #"+hex(iFlags)        
  end scope
  Cout("IDirect3D2::D3dDevice.DrawPrimitive (29) >> "+hexptr(pTHIS)+chr$(13,10) + _
  " >> Type:"+sType+"  Fmt:"+sFmt+"  Vert:"+hexptr(pVert)+"  Cnt:" & dwCount & "  Flags("+sFlags+" )")  
  #endif
  #endif  
  if pTHIS->Interface <> itd3dDevice2 then
    ddrawerror(DDERR_INVALIDOBJECT)
  end if
  if dwType=0 or dwFmt=0 or pVert=0 or cuint(dwCount)>65535 then
    ddrawerror(DDERR_INVALIDPARAMS)
  end if
  
  var pTex = pThis->SelTex
  if isBadReadPtr(pTex,sizeof(d3dDevice2Object)) then 
    pTex=0: pThis->SelTex=0
  end if
  if pTex andalso pTex->NeedUpdate then    
    var iTex = pTex->ID
    pTex->NeedUpdate =0: ogl.LastTex = iTex
    if pTex->bpp=8 then
      var pPal = pTex->Pal
      if pPal = 0 then
        #ifdef MyDebugErr
        lcout("NO PAL??? O_O")
        #endif
      else
        mt_glUpdateTexture8(pTex,pTex->Wid,pTex->Hei,cast(any ptr,pTex->fbImage+1),@(pPal->Pal(0)))
      end if
    else
      mt_glUpdateTexture16(pTex,pTex->Wid,pTex->Hei,cast(any ptr,pTex->fbImage+1))
    end if
  end if
  if dwCount > 0 then
    mt_DrawPrimitives(dwType,dwFmt,pVert,dwCount)'something
  end if
  #endif
  return DD_OK  
end function

' ****************************************************************************************
' ****************************************************************************************
' ****************************************************************************************
sub d3dDevice2Funcs(VTABLE() as any ptr)
  dim as any ptr PROTOTABLE
  asm mov dword ptr [PROTOTABLE], offset _d3dDevice2ProtoTable_
  for CNT as integer = 0 to 33
    VTABLE(CNT) = PROTOTABLE+CNT*32
  next CNT    
  #ifdef Render_OpenGL
  VTABLE( 2) = @d3dDevice2_2_Release  
  VTABLE( 6) = @d3dDevice2_6_AddViewport  
  VTABLE( 7) = @d3dDevice2_7_DeleteViewport
  VTABLE( 9) = @d3dDevice2_9_EnumTextureFormats
  VTABLE(10) = @d3dDevice2_10_BeginScene
  VTABLE(11) = @d3dDevice2_11_EndScene
  VTABLE(13) = @d3dDevice2_13_SetCurrentViewport
  VTABLE(23) = @d3dDevice2_23_SetRenderState
  VTABLE(25) = @d3dDevice2_25_SetLightState
  VTABLE(29) = @d3dDevice2_29_DrawPrimitive
  #endif
end sub
