Updated.
[wine] / dlls / ddraw / dpalette / main.c
1 /*              DirectDraw - IDirectPalette base interface
2  *
3  * Copyright 1997-2000 Marcus Meissner
4  * Copyright 2000 TransGaming Technologies Inc.
5  */
6
7 #include "config.h"
8 #include "winerror.h"
9 #include "debugtools.h"
10
11 #include <assert.h>
12 #include <string.h>
13
14 #include "ddraw_private.h"
15 #include "dpalette/main.h"
16 #include "ddraw/main.h"
17
18 DEFAULT_DEBUG_CHANNEL(ddraw);
19
20 #define SIZE_BITS (DDPCAPS_1BIT | DDPCAPS_2BIT | DDPCAPS_4BIT | DDPCAPS_8BIT)
21
22 /* For unsigned x. 0 is not a power of 2. */
23 #define IS_POW_2(x) (((x) & ((x) - 1)) == 0)
24
25 static ICOM_VTABLE(IDirectDrawPalette) DDRAW_Main_Palette_VTable;
26
27 /******************************************************************************
28  *                      IDirectDrawPalette
29  */
30 HRESULT Main_DirectDrawPalette_Construct(IDirectDrawPaletteImpl* This,
31                                          IDirectDrawImpl* pDD, DWORD dwFlags)
32 {
33     if (!IS_POW_2(dwFlags & SIZE_BITS)) return DDERR_INVALIDPARAMS;
34
35     if (dwFlags & DDPCAPS_8BITENTRIES)
36         WARN("creating palette with 8 bit entries\n");
37
38     This->flags = dwFlags;
39     This->palNumEntries = Main_DirectDrawPalette_Size(dwFlags);
40     This->ref = 1;
41     This->final_release = Main_DirectDrawPalette_final_release;
42     ICOM_INIT_INTERFACE(This, IDirectDrawPalette, DDRAW_Main_Palette_VTable);
43
44     /* we could defer hpal creation until we need it,
45      * but does anyone have a case where it would be useful? */
46     This->hpal = CreatePalette((const LOGPALETTE*)&(This->palVersion));
47
48     Main_DirectDraw_AddPalette(pDD, This);
49
50     return DD_OK;
51 }
52
53 HRESULT
54 Main_DirectDrawPalette_Create(IDirectDrawImpl* pDD, DWORD dwFlags,
55                               LPDIRECTDRAWPALETTE* ppPalette,
56                               LPUNKNOWN pUnkOuter)
57 {
58     IDirectDrawPaletteImpl* This;
59     HRESULT hr;
60
61     if (pUnkOuter != NULL)
62         return CLASS_E_NOAGGREGATION; /* unchecked */
63
64     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
65     if (This == NULL) return E_OUTOFMEMORY;
66
67     hr = Main_DirectDrawPalette_Construct(This, pDD, dwFlags);
68     if (FAILED(hr))
69         HeapFree(GetProcessHeap(), 0, This);
70     else
71         *ppPalette = ICOM_INTERFACE(This, IDirectDrawPalette);
72
73     return hr;
74 }
75
76 DWORD Main_DirectDrawPalette_Size(DWORD dwFlags)
77 {
78     switch (dwFlags & SIZE_BITS)
79     {
80     case DDPCAPS_1BIT: return 2;
81     case DDPCAPS_2BIT: return 4;
82     case DDPCAPS_4BIT: return 16;
83     case DDPCAPS_8BIT: return 256;
84     default: assert(0); return 256;
85     }
86 }
87
88 HRESULT WINAPI
89 Main_DirectDrawPalette_GetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
90                                   DWORD dwStart, DWORD dwCount,
91                                   LPPALETTEENTRY palent)
92 {
93     ICOM_THIS(IDirectDrawPaletteImpl,iface);
94
95     TRACE("(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",This,dwFlags,dwStart,dwCount,
96           palent);
97
98     if (dwFlags != 0) return DDERR_INVALIDPARAMS; /* unchecked */
99     if (dwStart + dwCount > Main_DirectDrawPalette_Size(This->flags))
100         return DDERR_INVALIDPARAMS;
101
102     if (This->flags & DDPCAPS_8BITENTRIES)
103     {
104         int i;
105         LPBYTE entry = (LPBYTE)palent;
106
107         for (i=dwStart; i < dwCount+dwStart; i++)
108             *entry++ = This->palents[i].peRed;
109     }
110     else
111         memcpy(palent, This->palents+dwStart, dwCount * sizeof(PALETTEENTRY));
112
113     return DD_OK;
114 }
115
116 HRESULT WINAPI
117 Main_DirectDrawPalette_SetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
118                                   DWORD dwStart, DWORD dwCount,
119                                   LPPALETTEENTRY palent)
120 {
121     ICOM_THIS(IDirectDrawPaletteImpl,iface);
122
123     TRACE("(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",This,dwFlags,dwStart,dwCount,
124           palent);
125
126     if (This->flags & DDPCAPS_8BITENTRIES)
127     {
128         int i;
129         const BYTE* entry = (const BYTE*)palent;
130
131         for (i=dwStart; i < dwCount+dwStart; i++)
132             This->palents[i].peRed = *entry++;
133     }
134     else {
135         memcpy(This->palents+dwStart, palent, dwCount * sizeof(PALETTEENTRY));
136
137         if (This->hpal)
138             SetPaletteEntries(This->hpal, dwStart, dwCount, This->palents+dwStart);
139
140         if (This->flags & DDPCAPS_PRIMARYSURFACE) {
141             /* update physical palette */
142             LPDIRECTDRAWSURFACE7 psurf = NULL;
143             IDirectDraw7_GetGDISurface(ICOM_INTERFACE(This->ddraw_owner,IDirectDraw7), &psurf);
144             if (psurf) {
145                 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
146                                                            IDirectDrawSurface7, psurf);
147                 surf->update_palette(surf, This, dwStart, dwCount, palent);
148                 IDirectDrawSurface7_Release(psurf);
149             }
150             else ERR("can't find GDI surface!!\n");
151         }
152     }
153
154 #if 0
155     /* Now, if we are in 'depth conversion mode', update the screen palette */
156     /* FIXME: we need to update the image or we won't get palette fading. */
157     if (This->ddraw->d->palette_convert != NULL)
158         This->ddraw->d->palette_convert(palent,This->screen_palents,start,count);
159 #endif
160
161     return DD_OK;
162 }
163
164 void Main_DirectDrawPalette_final_release(IDirectDrawPaletteImpl* This)
165 {
166     Main_DirectDraw_RemovePalette(This->ddraw_owner, This);
167
168     if (This->hpal) DeleteObject(This->hpal);
169 }
170
171 static void Main_DirectDrawPalette_Destroy(IDirectDrawPaletteImpl* This)
172 {
173     This->final_release(This);
174
175     if (This->private != This+1)
176         HeapFree(GetProcessHeap(), 0, This->private);
177                      
178     HeapFree(GetProcessHeap(),0,This);
179 }
180
181 void Main_DirectDrawPalette_ForceDestroy(IDirectDrawPaletteImpl* This)
182 {
183     WARN("deleting palette %p with refcnt %lu\n", This, This->ref);
184     Main_DirectDrawPalette_Destroy(This);
185 }
186
187 ULONG WINAPI
188 Main_DirectDrawPalette_Release(LPDIRECTDRAWPALETTE iface)
189 {
190     ICOM_THIS(IDirectDrawPaletteImpl,iface);
191     TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
192
193     if (!--This->ref)
194     {
195         Main_DirectDrawPalette_Destroy(This);
196         return 0;
197     }
198
199     return This->ref;
200 }
201
202 ULONG WINAPI Main_DirectDrawPalette_AddRef(LPDIRECTDRAWPALETTE iface) {
203     ICOM_THIS(IDirectDrawPaletteImpl,iface);
204     TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
205     return ++This->ref;
206 }
207
208 HRESULT WINAPI
209 Main_DirectDrawPalette_Initialize(LPDIRECTDRAWPALETTE iface,
210                                   LPDIRECTDRAW ddraw, DWORD dwFlags,
211                                   LPPALETTEENTRY palent)
212 {
213     ICOM_THIS(IDirectDrawPaletteImpl,iface);
214     TRACE("(%p)->(%p,%ld,%p)\n", This, ddraw, dwFlags, palent);
215     return DDERR_ALREADYINITIALIZED;
216 }
217
218 HRESULT WINAPI
219 Main_DirectDrawPalette_GetCaps(LPDIRECTDRAWPALETTE iface, LPDWORD lpdwCaps)
220 {
221    ICOM_THIS(IDirectDrawPaletteImpl,iface);
222    TRACE("(%p)->(%p)\n",This,lpdwCaps);
223
224    *lpdwCaps = This->flags;
225
226    return DD_OK;
227
228
229 HRESULT WINAPI
230 Main_DirectDrawPalette_QueryInterface(LPDIRECTDRAWPALETTE iface,
231                                       REFIID refiid, LPVOID *obj)
232 {
233     ICOM_THIS(IDirectDrawPaletteImpl,iface);
234     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
235
236     if (IsEqualGUID(refiid, &IID_IUnknown)
237         || IsEqualGUID(refiid, &IID_IDirectDrawPalette))
238     {
239         *obj = iface;
240         IDirectDrawPalette_AddRef(iface);
241         return S_OK;
242     }
243     else
244     {
245         return E_NOINTERFACE;
246     }
247 }
248
249 static ICOM_VTABLE(IDirectDrawPalette) DDRAW_Main_Palette_VTable =
250 {
251     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
252     Main_DirectDrawPalette_QueryInterface,
253     Main_DirectDrawPalette_AddRef,
254     Main_DirectDrawPalette_Release,
255     Main_DirectDrawPalette_GetCaps,
256     Main_DirectDrawPalette_GetEntries,
257     Main_DirectDrawPalette_Initialize,
258     Main_DirectDrawPalette_SetEntries
259 };