| /* Direct3D Light | 
 |    (c) 1998 Lionel ULMER | 
 |     | 
 |    This files contains the implementation of Direct3DLight. */ | 
 |  | 
 |  | 
 | #include "config.h" | 
 | #include "windef.h" | 
 | #include "winerror.h" | 
 | #include "wine/obj_base.h" | 
 | #include "heap.h" | 
 | #include "ddraw.h" | 
 | #include "d3d.h" | 
 | #include "debugtools.h" | 
 |  | 
 | #include "d3d_private.h" | 
 |  | 
 | DEFAULT_DEBUG_CHANNEL(ddraw) | 
 |  | 
 | #ifdef HAVE_MESAGL | 
 |  | 
 | static ICOM_VTABLE(IDirect3DLight) light_vtable; | 
 |  | 
 | enum { | 
 |   D3D_1, | 
 |   D3D_2 | 
 | }; | 
 |  | 
 | /******************************************************************************* | 
 |  *				Light static functions | 
 |  */ | 
 | static const float zero_value[] = { | 
 |   0.0, 0.0, 0.0, 0.0 | 
 | }; | 
 |  | 
 | static void update(IDirect3DLightImpl* This) { | 
 |   switch (This->light.dltType) { | 
 |   case D3DLIGHT_POINT:         /* 1 */ | 
 |     TRACE("Activating POINT\n"); | 
 |     break; | 
 |      | 
 |   case D3DLIGHT_SPOT:          /* 2 */ | 
 |     TRACE("Activating SPOT\n"); | 
 |     break; | 
 |      | 
 |   case D3DLIGHT_DIRECTIONAL: {  /* 3 */ | 
 |     float direction[4]; | 
 |      | 
 |     TRACE("Activating DIRECTIONAL\n"); | 
 |     TRACE("  direction : %f %f %f\n", | 
 | 	  This->light.dvDirection.x.x, | 
 | 	  This->light.dvDirection.y.y, | 
 | 	  This->light.dvDirection.z.z); | 
 |     _dump_colorvalue(" color    ", This->light.dcvColor); | 
 |  | 
 |     glLightfv(This->light_num, | 
 | 	      GL_AMBIENT, | 
 | 	      (float *) zero_value); | 
 |  | 
 |     glLightfv(This->light_num, | 
 | 	      GL_DIFFUSE, | 
 | 	      (float *) &(This->light.dcvColor)); | 
 |  | 
 |     direction[0] = -This->light.dvDirection.x.x; | 
 |     direction[1] = -This->light.dvDirection.y.y; | 
 |     direction[2] = -This->light.dvDirection.z.z; | 
 |     direction[3] = 0.0; /* This is a directional light */ | 
 |     glLightfv(This->light_num, | 
 | 	      GL_POSITION, | 
 | 	      (float *) direction); | 
 |   } break; | 
 |      | 
 |   case D3DLIGHT_PARALLELPOINT:  /* 4 */ | 
 |     TRACE("Activating PARRALLEL-POINT\n"); | 
 |     break; | 
 |  | 
 |   default: | 
 |     TRACE("Not a know Light Type\n"); | 
 |     break; | 
 |   } | 
 | } | 
 |  | 
 | static void activate(IDirect3DLightImpl* This) { | 
 |   ENTER_GL(); | 
 |   update(This); | 
 |  | 
 |   /* If was not active, activate it */ | 
 |   if (This->is_active == 0) { | 
 |     glEnable(This->light_num); | 
 |  | 
 |     This->is_active = 1; | 
 |   } | 
 |   LEAVE_GL(); | 
 |  | 
 |   return ; | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  *				Light Creation functions | 
 |  */ | 
 | LPDIRECT3DLIGHT d3dlight_create(IDirect3D2Impl* d3d2) | 
 | { | 
 |   IDirect3DLightImpl* light; | 
 |    | 
 |   light = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DLightImpl)); | 
 |   light->ref = 1; | 
 |   light->lpvtbl = &light_vtable; | 
 |   light->d3d.d3d2 = d3d2; | 
 |   light->type = D3D_2; | 
 |  | 
 |   light->next = NULL; | 
 |   light->prev = NULL; | 
 |   light->activate = activate; | 
 |   light->is_active = 0; | 
 |    | 
 |   return (LPDIRECT3DLIGHT)light; | 
 | } | 
 |  | 
 | LPDIRECT3DLIGHT d3dlight_create_dx3(IDirect3DImpl* d3d1) | 
 | { | 
 |   IDirect3DLightImpl* light; | 
 |    | 
 |   light = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DLightImpl)); | 
 |   light->ref = 1; | 
 |   light->lpvtbl = &light_vtable; | 
 |    | 
 |   light->d3d.d3d1 = d3d1; | 
 |   light->type = D3D_1; | 
 |    | 
 |   light->next = NULL; | 
 |   light->prev = NULL; | 
 |   light->activate = activate; | 
 |   light->is_active = 0; | 
 |    | 
 |   return (LPDIRECT3DLIGHT)light; | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  *				IDirect3DLight methods | 
 |  */ | 
 |  | 
 | static HRESULT WINAPI IDirect3DLightImpl_QueryInterface(LPDIRECT3DLIGHT iface, | 
 | 						    REFIID riid, | 
 | 						    LPVOID* ppvObj) | 
 | { | 
 |   ICOM_THIS(IDirect3DLightImpl,iface); | 
 |   char xrefiid[50]; | 
 |    | 
 |   WINE_StringFromCLSID((LPCLSID)riid,xrefiid); | 
 |   FIXME("(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj); | 
 |    | 
 |   return S_OK; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | static ULONG WINAPI IDirect3DLightImpl_AddRef(LPDIRECT3DLIGHT iface) | 
 | { | 
 |   ICOM_THIS(IDirect3DLightImpl,iface); | 
 |   TRACE("(%p)->()incrementing from %lu.\n", This, This->ref ); | 
 |    | 
 |   return ++(This->ref); | 
 | } | 
 |  | 
 |  | 
 |  | 
 | static ULONG WINAPI IDirect3DLightImpl_Release(LPDIRECT3DLIGHT iface) | 
 | { | 
 |   ICOM_THIS(IDirect3DLightImpl,iface); | 
 |   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref ); | 
 |    | 
 |   if (!--(This->ref)) { | 
 |     HeapFree(GetProcessHeap(),0,This); | 
 |     return 0; | 
 |   } | 
 |    | 
 |   return This->ref; | 
 | } | 
 |  | 
 | /*** IDirect3DLight methods ***/ | 
 | static void dump_light(LPD3DLIGHT light) | 
 | { | 
 |   fprintf(stderr, "  dwSize : %ld\n", light->dwSize); | 
 | } | 
 |  | 
 | static HRESULT WINAPI IDirect3DLightImpl_GetLight(LPDIRECT3DLIGHT iface, | 
 | 					      LPD3DLIGHT lpLight) | 
 | { | 
 |   ICOM_THIS(IDirect3DLightImpl,iface); | 
 |   TRACE("(%p)->(%p)\n", This, lpLight); | 
 |   if (TRACE_ON(ddraw)) | 
 |     dump_light(lpLight); | 
 |    | 
 |   /* Copies the light structure */ | 
 |   switch (This->type) { | 
 |   case D3D_1: | 
 |     *((LPD3DLIGHT)lpLight) = *((LPD3DLIGHT) &(This->light)); | 
 |     break; | 
 |   case D3D_2: | 
 |     *((LPD3DLIGHT2)lpLight) = *((LPD3DLIGHT2) &(This->light)); | 
 |     break; | 
 |   } | 
 |    | 
 |   return DD_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI IDirect3DLightImpl_SetLight(LPDIRECT3DLIGHT iface, | 
 | 					      LPD3DLIGHT lpLight) | 
 | { | 
 |   ICOM_THIS(IDirect3DLightImpl,iface); | 
 |   TRACE("(%p)->(%p)\n", This, lpLight); | 
 |   if (TRACE_ON(ddraw)) | 
 |     dump_light(lpLight); | 
 |    | 
 |   /* Stores the light */ | 
 |   switch (This->type) { | 
 |   case D3D_1: | 
 |     *((LPD3DLIGHT) &(This->light)) = *((LPD3DLIGHT)lpLight); | 
 |     break; | 
 |   case D3D_2: | 
 |     *((LPD3DLIGHT2) &(This->light)) = *((LPD3DLIGHT2)lpLight); | 
 |     break; | 
 |   } | 
 |    | 
 |   ENTER_GL(); | 
 |   if (This->is_active) | 
 |     update(This); | 
 |   LEAVE_GL(); | 
 |    | 
 |   return DD_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI IDirect3DLightImpl_Initialize(LPDIRECT3DLIGHT iface, | 
 | 						LPDIRECT3D lpDirect3D) | 
 |  | 
 | { | 
 |   ICOM_THIS(IDirect3DLightImpl,iface); | 
 |   TRACE("(%p)->(%p)\n", This, lpDirect3D); | 
 |  | 
 |   return DDERR_ALREADYINITIALIZED; | 
 | } | 
 |  | 
 |  | 
 | /******************************************************************************* | 
 |  *				IDirect3DLight VTable | 
 |  */ | 
 | static ICOM_VTABLE(IDirect3DLight) light_vtable =  | 
 | { | 
 |   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE | 
 |   /*** IUnknown methods ***/ | 
 |   IDirect3DLightImpl_QueryInterface, | 
 |   IDirect3DLightImpl_AddRef, | 
 |   IDirect3DLightImpl_Release, | 
 |   /*** IDirect3DLight methods ***/ | 
 |   IDirect3DLightImpl_Initialize, | 
 |   IDirect3DLightImpl_SetLight, | 
 |   IDirect3DLightImpl_GetLight | 
 | }; | 
 |  | 
 | #else /* HAVE_MESAGL */ | 
 |  | 
 | /* These function should never be called if MesaGL is not present */ | 
 | LPDIRECT3DLIGHT d3dlight_create_dx3(IDirect3DImpl* d3d1) { | 
 |   ERR("Should not be called...\n"); | 
 |   return NULL; | 
 | } | 
 |  | 
 | LPDIRECT3DLIGHT d3dlight_create(IDirect3D2Impl* d3d2) { | 
 |   ERR("Should not be called...\n"); | 
 |   return NULL; | 
 | } | 
 |  | 
 | #endif /* HAVE_MESAGL */ |