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