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