xref: /reactos/dll/directx/wine/ddraw/palette.c (revision 34593d93)
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