xref: /reactos/dll/directx/wine/ddraw/palette.c (revision 8a978a17)
1 /*
2  * Copyright 2006 Stefan Dösinger
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "config.h"
20 #include "wine/port.h"
21 
22 #include "ddraw_private.h"
23 
24 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
25 
26 /*****************************************************************************
27  * IDirectDrawPalette::QueryInterface
28  *
29  * A usual QueryInterface implementation. Can only Query IUnknown and
30  * IDirectDrawPalette
31  *
32  * Params:
33  *  refiid: The interface id queried for
34  *  obj: Address to return the interface pointer at
35  *
36  * Returns:
37  *  S_OK on success
38  *  E_NOINTERFACE if the requested interface wasn't found
39  *****************************************************************************/
40 static HRESULT WINAPI ddraw_palette_QueryInterface(IDirectDrawPalette *iface, REFIID refiid, void **obj)
41 {
42     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
43 
44     if (IsEqualGUID(refiid, &IID_IUnknown)
45         || IsEqualGUID(refiid, &IID_IDirectDrawPalette))
46     {
47         *obj = iface;
48         IDirectDrawPalette_AddRef(iface);
49         return S_OK;
50     }
51     else
52     {
53         *obj = NULL;
54         return E_NOINTERFACE;
55     }
56 }
57 
58 /*****************************************************************************
59  * IDirectDrawPaletteImpl::AddRef
60  *
61  * Increases the refcount.
62  *
63  * Returns:
64  *  The new refcount
65  *
66  *****************************************************************************/
67 static ULONG WINAPI ddraw_palette_AddRef(IDirectDrawPalette *iface)
68 {
69     struct ddraw_palette *This = impl_from_IDirectDrawPalette(iface);
70     ULONG ref = InterlockedIncrement(&This->ref);
71 
72     TRACE("%p increasing refcount to %u.\n", This, ref);
73 
74     return ref;
75 }
76 
77 /*****************************************************************************
78  * IDirectDrawPaletteImpl::Release
79  *
80  * Reduces the refcount. If the refcount falls to 0, the object is destroyed
81  *
82  * Returns:
83  *  The new refcount
84  *
85  *****************************************************************************/
86 static ULONG WINAPI ddraw_palette_Release(IDirectDrawPalette *iface)
87 {
88     struct ddraw_palette *palette = impl_from_IDirectDrawPalette(iface);
89     ULONG ref = InterlockedDecrement(&palette->ref);
90 
91     TRACE("%p decreasing refcount to %u.\n", palette, ref);
92 
93     if (ref == 0)
94     {
95         wined3d_mutex_lock();
96         wined3d_palette_decref(palette->wined3d_palette);
97         if ((palette->flags & DDPCAPS_PRIMARYSURFACE) && palette->ddraw->primary)
98             palette->ddraw->primary->palette = NULL;
99         if (palette->ifaceToRelease)
100             IUnknown_Release(palette->ifaceToRelease);
101         wined3d_mutex_unlock();
102 
103         heap_free(palette);
104     }
105 
106     return ref;
107 }
108 
109 /*****************************************************************************
110  * IDirectDrawPalette::Initialize
111  *
112  * Initializes the palette. As we start initialized, return
113  * DDERR_ALREADYINITIALIZED
114  *
115  * Params:
116  *  DD: DirectDraw interface this palette is assigned to
117  *  Flags: Some flags, as usual
118  *  ColorTable: The startup color table
119  *
120  * Returns:
121  *  DDERR_ALREADYINITIALIZED
122  *
123  *****************************************************************************/
124 static HRESULT WINAPI ddraw_palette_Initialize(IDirectDrawPalette *iface,
125         IDirectDraw *ddraw, DWORD flags, PALETTEENTRY *entries)
126 {
127     TRACE("iface %p, ddraw %p, flags %#x, entries %p.\n",
128             iface, ddraw, flags, entries);
129 
130     return DDERR_ALREADYINITIALIZED;
131 }
132 
133 static HRESULT WINAPI ddraw_palette_GetCaps(IDirectDrawPalette *iface, DWORD *caps)
134 {
135     struct ddraw_palette *palette = impl_from_IDirectDrawPalette(iface);
136 
137     TRACE("iface %p, caps %p.\n", iface, caps);
138 
139     wined3d_mutex_lock();
140     *caps = palette->flags;
141     wined3d_mutex_unlock();
142 
143     return D3D_OK;
144 }
145 
146 /*****************************************************************************
147  * IDirectDrawPalette::SetEntries
148  *
149  * Sets the palette entries from a PALETTEENTRY structure. WineD3D takes
150  * care for updating the surface.
151  *
152  * Params:
153  *  Flags: Flags, as usual
154  *  Start: First palette entry to set
155  *  Count: Number of entries to set
156  *  PalEnt: Source entries
157  *
158  * Returns:
159  *  D3D_OK on success
160  *  DDERR_INVALIDPARAMS if PalEnt is NULL
161  *
162  *****************************************************************************/
163 static HRESULT WINAPI ddraw_palette_SetEntries(IDirectDrawPalette *iface,
164         DWORD flags, DWORD start, DWORD count, PALETTEENTRY *entries)
165 {
166     struct ddraw_palette *palette = impl_from_IDirectDrawPalette(iface);
167     HRESULT hr;
168 
169     TRACE("iface %p, flags %#x, start %u, count %u, entries %p.\n",
170             iface, flags, start, count, entries);
171 
172     if (!entries)
173         return DDERR_INVALIDPARAMS;
174 
175     wined3d_mutex_lock();
176     hr = wined3d_palette_set_entries(palette->wined3d_palette, flags, start, count, entries);
177 
178     if (SUCCEEDED(hr) && palette->flags & DDPCAPS_PRIMARYSURFACE)
179         ddraw_surface_update_frontbuffer(palette->ddraw->primary, NULL, FALSE);
180 
181     wined3d_mutex_unlock();
182 
183     return hr;
184 }
185 
186 /*****************************************************************************
187  * IDirectDrawPalette::GetEntries
188  *
189  * Returns the entries stored in this interface.
190  *
191  * Params:
192  *  Flags: Flags :)
193  *  Start: First entry to return
194  *  Count: The number of entries to return
195  *  PalEnt: PALETTEENTRY structure to write the entries to
196  *
197  * Returns:
198  *  D3D_OK on success
199  *  DDERR_INVALIDPARAMS if PalEnt is NULL
200  *
201  *****************************************************************************/
202 static HRESULT WINAPI ddraw_palette_GetEntries(IDirectDrawPalette *iface,
203         DWORD flags, DWORD start, DWORD count, PALETTEENTRY *entries)
204 {
205     struct ddraw_palette *palette = impl_from_IDirectDrawPalette(iface);
206     HRESULT hr;
207 
208     TRACE("iface %p, flags %#x, start %u, count %u, entries %p.\n",
209             iface, flags, start, count, entries);
210 
211     if (!entries)
212         return DDERR_INVALIDPARAMS;
213 
214     wined3d_mutex_lock();
215     hr = wined3d_palette_get_entries(palette->wined3d_palette, flags, start, count, entries);
216     wined3d_mutex_unlock();
217 
218     return hr;
219 }
220 
221 static const struct IDirectDrawPaletteVtbl ddraw_palette_vtbl =
222 {
223     /*** IUnknown ***/
224     ddraw_palette_QueryInterface,
225     ddraw_palette_AddRef,
226     ddraw_palette_Release,
227     /*** IDirectDrawPalette ***/
228     ddraw_palette_GetCaps,
229     ddraw_palette_GetEntries,
230     ddraw_palette_Initialize,
231     ddraw_palette_SetEntries
232 };
233 
234 struct ddraw_palette *unsafe_impl_from_IDirectDrawPalette(IDirectDrawPalette *iface)
235 {
236     if (!iface) return NULL;
237     assert(iface->lpVtbl == &ddraw_palette_vtbl);
238     return CONTAINING_RECORD(iface, struct ddraw_palette, IDirectDrawPalette_iface);
239 }
240 
241 static unsigned int palette_size(DWORD flags)
242 {
243     switch (flags & (DDPCAPS_1BIT | DDPCAPS_2BIT | DDPCAPS_4BIT | DDPCAPS_8BIT))
244     {
245         case DDPCAPS_1BIT:
246             return 2;
247         case DDPCAPS_2BIT:
248             return 4;
249         case DDPCAPS_4BIT:
250             return 16;
251         case DDPCAPS_8BIT:
252             return 256;
253         default:
254             return ~0u;
255     }
256 }
257 
258 HRESULT ddraw_palette_init(struct ddraw_palette *palette,
259         struct ddraw *ddraw, DWORD flags, PALETTEENTRY *entries)
260 {
261     unsigned int entry_count;
262     DWORD wined3d_flags = 0;
263     HRESULT hr;
264 
265     if ((entry_count = palette_size(flags)) == ~0u)
266     {
267         WARN("Invalid flags %#x.\n", flags);
268         return DDERR_INVALIDPARAMS;
269     }
270 
271     if (flags & DDPCAPS_8BITENTRIES)
272         wined3d_flags |= WINED3D_PALETTE_8BIT_ENTRIES;
273     if (flags & DDPCAPS_ALLOW256)
274         wined3d_flags |= WINED3D_PALETTE_ALLOW_256;
275     if (flags & DDPCAPS_ALPHA)
276         wined3d_flags |= WINED3D_PALETTE_ALPHA;
277 
278     palette->IDirectDrawPalette_iface.lpVtbl = &ddraw_palette_vtbl;
279     palette->ref = 1;
280     palette->flags = flags;
281 
282     if (FAILED(hr = wined3d_palette_create(ddraw->wined3d_device,
283             wined3d_flags, entry_count, entries, &palette->wined3d_palette)))
284     {
285         WARN("Failed to create wined3d palette, hr %#x.\n", hr);
286         return hr;
287     }
288 
289     palette->ddraw = ddraw;
290     palette->ifaceToRelease = (IUnknown *)&ddraw->IDirectDraw7_iface;
291     IUnknown_AddRef(palette->ifaceToRelease);
292 
293     return DD_OK;
294 }
295