Added native and emulated S3TC support.
[wine/multimedia.git] / dlls / ddraw / dsurface / main.c
blobf4d26f5927a2d97f2b3b61afd238868ed8593fc6
1 /* DirectDrawSurface base implementation
3 * Copyright 1997-2000 Marcus Meissner
4 * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5 * Copyright 2000-2001 TransGaming Technologies Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <assert.h>
24 #include <string.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "winerror.h"
29 #include "mesa_private.h"
30 #include "wine/debug.h"
31 #include "ddraw_private.h"
32 #include "dsurface/main.h"
33 #include "ddraw/main.h"
34 #include "dsurface/thunks.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 WINE_DECLARE_DEBUG_CHANNEL(ddraw_flip);
38 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);
40 /** Creation/Destruction functions */
42 HRESULT
43 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
44 IDirectDrawImpl *pDD,
45 const DDSURFACEDESC2 *pDDSD)
47 TRACE("(%p)->(%p,%p)\n", This, pDD, pDDSD);
49 if (pDDSD != &This->surface_desc) {
50 This->surface_desc.dwSize = sizeof(This->surface_desc);
51 DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
53 This->uniqueness_value = 1; /* unchecked */
54 This->ref = 1;
56 This->local.lpSurfMore = &This->more;
57 This->local.lpGbl = &This->global;
58 This->local.dwProcessId = GetCurrentProcessId();
59 This->local.dwFlags = 0; /* FIXME */
60 This->local.ddsCaps.dwCaps = This->surface_desc.ddsCaps.dwCaps;
61 /* FIXME: more local stuff */
62 This->more.lpDD_lcl = &pDD->local;
63 This->more.ddsCapsEx.dwCaps2 = This->surface_desc.ddsCaps.dwCaps2;
64 This->more.ddsCapsEx.dwCaps3 = This->surface_desc.ddsCaps.dwCaps3;
65 This->more.ddsCapsEx.dwCaps4 = This->surface_desc.ddsCaps.dwCaps4;
66 /* FIXME: more more stuff */
67 This->gmore = &This->global_more;
68 This->global.u3.lpDD = pDD->local.lpGbl;
69 /* FIXME: more global stuff */
71 This->final_release = Main_DirectDrawSurface_final_release;
72 This->late_allocate = Main_DirectDrawSurface_late_allocate;
73 This->attach = Main_DirectDrawSurface_attach;
74 This->detach = Main_DirectDrawSurface_detach;
75 This->lock_update = Main_DirectDrawSurface_lock_update;
76 This->unlock_update = Main_DirectDrawSurface_unlock_update;
77 This->lose_surface = Main_DirectDrawSurface_lose_surface;
78 This->set_palette = Main_DirectDrawSurface_set_palette;
79 This->update_palette = Main_DirectDrawSurface_update_palette;
80 This->get_display_window = Main_DirectDrawSurface_get_display_window;
81 This->get_gamma_ramp = Main_DirectDrawSurface_get_gamma_ramp;
82 This->set_gamma_ramp = Main_DirectDrawSurface_set_gamma_ramp;
84 ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
85 DDRAW_IDDS3_Thunk_VTable);
86 ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
87 DDRAW_IDDGC_VTable);
89 /* There is no generic implementation of IDDS7 or texture */
91 Main_DirectDraw_AddSurface(pDD, This);
92 return DD_OK;
95 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
97 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
100 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
102 return DD_OK;
105 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
107 if (This->palette) {
108 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette, IDirectDrawPalette));
109 This->palette = NULL;
111 This->final_release(This);
112 if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
113 if (This->tex_private) HeapFree(GetProcessHeap(), 0, This->tex_private);
114 HeapFree(GetProcessHeap(), 0, This);
117 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
119 WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
120 Main_DirectDrawSurface_Destroy(This);
123 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
125 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
127 TRACE("(%p)->(): decreasing from %ld\n", This, This->ref);
129 if (--This->ref == 0)
131 if (This->aux_release)
132 This->aux_release(This->aux_ctx, This->aux_data);
133 Main_DirectDrawSurface_Destroy(This);
135 TRACE("released surface %p\n", This);
137 return 0;
140 return This->ref;
143 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
145 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
147 TRACE("(%p)->(): increasing from %ld\n", This, This->ref);
149 return ++This->ref;
152 HRESULT WINAPI
153 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
154 LPVOID* ppObj)
156 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
157 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
159 *ppObj = NULL;
161 if (IsEqualGUID(&IID_IUnknown, riid)
162 || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
163 || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
165 This->ref++;
166 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
167 return S_OK;
169 else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
170 || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
171 || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
173 This->ref++;
174 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
175 return S_OK;
177 else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
179 This->ref++;
180 *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
181 return S_OK;
183 #ifdef HAVE_OPENGL
184 /* interfaces following here require OpenGL */
185 if( !opengl_initialized )
186 return E_NOINTERFACE;
188 if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL, riid ) ||
189 IsEqualGUID( &IID_IDirect3DHALDevice, riid) )
191 IDirect3DDeviceImpl *d3ddevimpl;
192 HRESULT ret_value;
194 ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, TRUE);
195 if (FAILED(ret_value)) return ret_value;
197 *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
198 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj);
200 This->ref++; /* No idea if this is correct.. Need to check using real Windows */
201 return ret_value;
203 else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
204 IsEqualGUID( &IID_IDirect3DTexture2, riid ))
206 HRESULT ret_value = S_OK;
208 /* Note: this is not exactly how Windows does it... But this seems not to hurt the only
209 application I know creating a texture without this flag set and it will prevent
210 bugs in other parts of Wine.
212 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
214 /* In case the texture surface was created before the D3D creation */
215 if (This->tex_private == NULL) {
216 if (This->ddraw_owner->d3d_private == NULL) {
217 ERR("Texture created with no D3D object yet.. Not supported !\n");
218 return E_NOINTERFACE;
221 ret_value = This->ddraw_owner->d3d_create_texture(This->ddraw_owner, This, FALSE, This->mip_main);
222 if (FAILED(ret_value)) return ret_value;
224 if (IsEqualGUID( &IID_IDirect3DTexture, riid )) {
225 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture);
226 TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj);
227 } else {
228 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture2);
229 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj);
231 This->ref++;
232 return ret_value;
234 #endif
236 return E_NOINTERFACE;
239 /*** Callbacks */
241 BOOL
242 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
243 IDirectDrawSurfaceImpl *to)
245 return TRUE;
248 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
250 return TRUE;
253 void
254 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
255 DWORD dwFlags)
259 void
260 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
261 LPCRECT pRect)
265 void
266 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
270 void
271 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
272 IDirectDrawPaletteImpl* pal)
276 void
277 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
278 IDirectDrawPaletteImpl* pal,
279 DWORD dwStart, DWORD dwCount,
280 LPPALETTEENTRY palent)
284 HWND
285 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
287 return 0;
290 HRESULT
291 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
292 DWORD dwFlags,
293 LPDDGAMMARAMP lpGammaRamp)
295 HDC hDC;
296 HRESULT hr;
297 hr = This->get_dc(This, &hDC);
298 if (FAILED(hr)) return hr;
299 hr = GetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
300 This->release_dc(This, hDC);
301 return hr;
304 HRESULT
305 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
306 DWORD dwFlags,
307 LPDDGAMMARAMP lpGammaRamp)
309 HDC hDC;
310 HRESULT hr;
311 hr = This->get_dc(This, &hDC);
312 if (FAILED(hr)) return hr;
313 hr = SetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
314 This->release_dc(This, hDC);
315 return hr;
319 /*** Interface functions */
321 HRESULT WINAPI
322 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
323 LPDIRECTDRAWSURFACE7 pAttach)
325 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
326 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
327 IDirectDrawSurface7, pAttach);
329 TRACE("(%p)->(%p)\n",This,pAttach);
331 /* Does windows check this? */
332 if (surf == This)
333 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
335 /* Does windows check this? */
336 if (surf->ddraw_owner != This->ddraw_owner)
337 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
339 if (surf->surface_owner != NULL)
340 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
342 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
343 * But apparently backbuffers and mipmaps can be attached too. */
345 /* Set MIPMAPSUBLEVEL if this seems to be one */
346 if (This->surface_desc.ddsCaps.dwCaps &
347 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
348 surf->surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
349 /* FIXME: we should probably also add to dwMipMapCount of this
350 * and all parent surfaces (update create_texture if you do) */
353 /* Callback to allow the surface to do something special now that it is
354 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
355 if (!surf->attach(surf, This))
356 return DDERR_CANNOTATTACHSURFACE;
358 /* check: Where should it go in the chain? This puts it on the head. */
359 if (This->attached)
360 This->attached->prev_attached = surf;
361 surf->next_attached = This->attached;
362 surf->prev_attached = NULL;
363 This->attached = surf;
364 surf->surface_owner = This;
366 IDirectDrawSurface7_AddRef(pAttach);
368 return DD_OK;
371 /* MSDN: "not currently implemented." */
372 HRESULT WINAPI
373 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
374 LPRECT pRect)
376 TRACE("(%p)->(%p)\n",iface,pRect);
377 return DDERR_UNSUPPORTED; /* unchecked */
380 /* MSDN: "not currently implemented." */
381 HRESULT WINAPI
382 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
383 LPDDBLTBATCH pBatch, DWORD dwCount,
384 DWORD dwFlags)
386 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
387 return DDERR_UNSUPPORTED; /* unchecked */
390 HRESULT WINAPI
391 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
393 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
394 volatile IDirectDrawSurfaceImpl* vThis = This;
396 TRACE("(%p)\n",This);
397 /* A uniquness value of 0 is apparently special.
398 * This needs to be checked. */
399 while (1)
401 DWORD old_uniqueness_value = vThis->uniqueness_value;
402 DWORD new_uniqueness_value = old_uniqueness_value+1;
404 if (old_uniqueness_value == 0) break;
405 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
407 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
408 old_uniqueness_value,
409 new_uniqueness_value)
410 == old_uniqueness_value)
411 break;
414 return DD_OK;
417 HRESULT WINAPI
418 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
419 DWORD dwFlags,
420 LPDIRECTDRAWSURFACE7 pAttach)
422 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
423 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
424 IDirectDrawSurface7, pAttach);
426 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
428 if (!surf || (surf->surface_owner != This))
429 return DDERR_SURFACENOTATTACHED; /* unchecked */
431 surf->detach(surf);
433 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
434 if (This->surface_desc.ddsCaps.dwCaps &
435 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
436 surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
437 /* FIXME: we should probably also subtract from dwMipMapCount of this
438 * and all parent surfaces */
441 if (surf->next_attached)
442 surf->next_attached->prev_attached = surf->prev_attached;
443 if (surf->prev_attached)
444 surf->prev_attached->next_attached = surf->next_attached;
445 if (This->attached == surf)
446 This->attached = surf->next_attached;
448 IDirectDrawSurface7_Release(pAttach);
450 return DD_OK;
453 HRESULT WINAPI
454 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
455 LPVOID context,
456 LPDDENUMSURFACESCALLBACK7 cb)
458 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
459 IDirectDrawSurfaceImpl* surf;
461 TRACE("(%p)->(%p,%p)\n",This,context,cb);
463 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
465 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
466 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
467 context) == DDENUMRET_CANCEL)
468 break;
471 return DD_OK;
474 HRESULT WINAPI
475 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
476 DWORD dwFlags, LPVOID context,
477 LPDDENUMSURFACESCALLBACK7 cb)
479 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
480 return DD_OK;
483 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
484 IDirectDrawSurfaceImpl* back,
485 DWORD dwFlags)
487 /* uniqueness_value? */
488 /* This is necessary. But is it safe? */
490 HDC tmp = front->hDC;
491 front->hDC = back->hDC;
492 back->hDC = tmp;
496 BOOL tmp = front->dc_in_use;
497 front->dc_in_use = back->dc_in_use;
498 back->dc_in_use = tmp;
502 FLATPTR tmp = front->global.fpVidMem;
503 front->global.fpVidMem = back->global.fpVidMem;
504 back->global.fpVidMem = tmp;
508 ULONG_PTR tmp = front->global_more.hKernelSurface;
509 front->global_more.hKernelSurface = back->global_more.hKernelSurface;
510 back->global_more.hKernelSurface = tmp;
513 return TRUE;
516 /* This is unnecessarely complicated :-) */
517 #define MEASUREMENT_WINDOW 5
518 #define NUMBER_OF_WINDOWS 10
520 static LONGLONG perf_freq;
521 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
522 static LONGLONG prev_time = 0;
523 static unsigned int current_window;
524 static unsigned int measurements_in_window;
525 static unsigned int valid_windows;
527 HRESULT WINAPI
528 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
529 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
531 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
532 IDirectDrawSurfaceImpl* target;
533 HRESULT hr;
535 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
537 if (TRACE_ON(ddraw_fps)) {
538 LONGLONG current_time;
539 LONGLONG frame_duration;
540 QueryPerformanceCounter((LARGE_INTEGER *) &current_time);
542 if (prev_time != 0) {
543 LONGLONG total_time = 0;
544 int tot_meas;
546 frame_duration = current_time - prev_time;
547 prev_time = current_time;
549 perf_storage[current_window] += frame_duration;
550 measurements_in_window++;
552 if (measurements_in_window >= MEASUREMENT_WINDOW) {
553 current_window++;
554 valid_windows++;
556 if (valid_windows < NUMBER_OF_WINDOWS) {
557 int i;
558 tot_meas = valid_windows * MEASUREMENT_WINDOW;
559 for (i = 0; i < valid_windows; i++) {
560 total_time += perf_storage[i];
562 } else {
563 int i;
564 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
565 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
566 total_time += perf_storage[i];
570 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
572 if (current_window >= NUMBER_OF_WINDOWS) {
573 current_window = 0;
575 perf_storage[current_window] = 0;
576 measurements_in_window = 0;
578 } else {
579 prev_time = current_time;
580 memset(perf_storage, 0, sizeof(perf_storage));
581 current_window = 0;
582 valid_windows = 0;
583 measurements_in_window = 0;
584 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
588 /* MSDN: "This method can be called only for a surface that has the
589 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
590 if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
591 != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
592 return DDERR_NOTFLIPPABLE;
594 if (This->aux_flip)
595 if (This->aux_flip(This->aux_ctx, This->aux_data))
596 return DD_OK;
598 /* 1. find the flip target */
599 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
600 if (override == NULL)
602 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
603 LPDIRECTDRAWSURFACE7 tgt;
605 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
606 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
608 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
609 tgt);
610 IDirectDrawSurface7_Release(tgt);
612 else
614 BOOL on_chain = FALSE;
615 IDirectDrawSurfaceImpl* surf;
617 /* MSDN: "The method fails if the specified [override] surface is not
618 * a member of the flipping chain." */
620 /* Verify that override is on this flip chain. We assume that
621 * surf is the head of the flipping chain, because it's the front
622 * buffer. */
623 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
624 override);
626 /* Either target is (indirectly) attached to This or This is
627 * (indirectly) attached to target. */
628 for (surf = target; surf != NULL; surf = surf->surface_owner)
630 if (surf == This)
632 on_chain = TRUE;
633 break;
637 if (!on_chain)
638 return DDERR_INVALIDPARAMS; /* unchecked */
641 TRACE("flip to backbuffer: %p\n",target);
642 if (TRACE_ON(ddraw_flip)) {
643 static unsigned int flip_count = 0;
644 IDirectDrawPaletteImpl *palette;
645 char buf[32];
646 FILE *f;
648 /* Hack for paletted games... */
649 palette = target->palette;
650 target->palette = This->palette;
652 sprintf(buf, "flip_%08d.ppm", flip_count++);
653 TRACE_(ddraw_flip)("Dumping file %s to disk.\n", buf);
654 f = fopen(buf, "wb");
655 DDRAW_dump_surface_to_disk(target, f, 8);
656 target->palette = palette;
659 if (This->flip_data(This, target, dwFlags))
660 This->flip_update(This, dwFlags);
662 return DD_OK;
665 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
666 REFGUID tag)
668 PrivateData* data;
669 for (data = This->private_data; data != NULL; data = data->next)
671 if (IsEqualGUID(&data->tag, tag)) break;
674 return data;
677 HRESULT WINAPI
678 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
680 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
681 PrivateData *data;
683 data = find_private_data(This, tag);
684 if (data == NULL) return DDERR_NOTFOUND;
686 if (data->prev)
687 data->prev->next = data->next;
688 if (data->next)
689 data->next->prev = data->prev;
691 if (data->flags & DDSPD_IUNKNOWNPTR)
693 if (data->ptr.object != NULL)
694 IUnknown_Release(data->ptr.object);
696 else
697 HeapFree(GetProcessHeap(), 0, data->ptr.data);
699 HeapFree(GetProcessHeap(), 0, data);
701 return DD_OK;
704 HRESULT WINAPI
705 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
706 LPDDSCAPS2 pCaps,
707 LPDIRECTDRAWSURFACE7* ppSurface)
709 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
710 IDirectDrawSurfaceImpl* surf;
711 IDirectDrawSurfaceImpl* found = NULL;
712 DDSCAPS2 our_caps;
714 if (TRACE_ON(ddraw)) {
715 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
716 pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
717 TRACE(" Caps are : "); DDRAW_dump_DDSCAPS2(pCaps); TRACE("\n");
720 our_caps = *pCaps;
721 if ((This->ddraw_owner->local.dwLocalFlags & DDRAWILCL_DIRECTDRAW7) == 0) {
722 /* As this is not a DirectDraw7 application, remove the garbage that some games
723 put in the new fields of the DDSCAPS2 structure. */
724 our_caps.dwCaps2 = 0;
725 our_caps.dwCaps3 = 0;
726 our_caps.dwCaps4 = 0;
727 if (TRACE_ON(ddraw)) {
728 TRACE(" Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps); TRACE("\n");
732 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
734 if (TRACE_ON(ddraw)) {
735 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
736 surf->surface_desc.ddsCaps.dwCaps,
737 surf->surface_desc.ddsCaps.dwCaps2,
738 surf->surface_desc.ddsCaps.dwCaps3,
739 surf->surface_desc.ddsCaps.dwCaps4);
740 TRACE(" Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf->surface_desc.ddsCaps)); TRACE("\n");
742 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
743 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2))
745 /* MSDN: "This method fails if more than one surface is attached
746 * that matches the capabilities requested." */
747 if (found != NULL)
749 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
750 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
751 to be correct, given what 3DMark expects from MipMapped surfaces.
752 We shall just continue instead. */
755 found = surf;
759 if (found == NULL) {
760 TRACE("Did not find any valid surface\n");
761 return DDERR_NOTFOUND;
764 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
766 if (TRACE_ON(ddraw)) {
767 TRACE("Returning surface %p with description : \n", *ppSurface);
768 DDRAW_dump_surface_desc(&(found->surface_desc));
771 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
772 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
773 return DD_OK;
776 HRESULT WINAPI
777 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
779 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
781 switch (dwFlags)
783 case DDGBS_CANBLT:
784 case DDGBS_ISBLTDONE:
785 return DD_OK;
787 default:
788 return DDERR_INVALIDPARAMS;
792 HRESULT WINAPI
793 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
795 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
797 TRACE("(%p)->(%p)\n",This,pCaps);
798 *pCaps = This->surface_desc.ddsCaps;
799 return DD_OK;
802 HRESULT WINAPI
803 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
804 LPDIRECTDRAWCLIPPER* ppClipper)
806 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
808 TRACE("(%p)->(%p)\n",This,ppClipper);
809 if (This->clipper == NULL)
810 return DDERR_NOCLIPPERATTACHED;
812 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
813 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
814 IDirectDrawClipper));
815 return DD_OK;
818 HRESULT WINAPI
819 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
820 LPDDCOLORKEY pCKey)
822 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
823 * isn't there? That's like saying that an int isn't there. (Which MS
824 * has done in other docs.) */
826 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
828 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
829 if (TRACE_ON(ddraw)) {
830 TRACE(" - colorkey flags : ");
831 DDRAW_dump_colorkeyflag(dwFlags);
834 switch (dwFlags)
836 case DDCKEY_DESTBLT:
837 *pCKey = This->surface_desc.ddckCKDestBlt;
838 break;
840 case DDCKEY_DESTOVERLAY:
841 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
842 break;
844 case DDCKEY_SRCBLT:
845 *pCKey = This->surface_desc.ddckCKSrcBlt;
846 break;
848 case DDCKEY_SRCOVERLAY:
849 *pCKey = This->surface_desc.ddckCKSrcOverlay;
850 break;
852 default:
853 return DDERR_INVALIDPARAMS;
856 return DD_OK;
859 /* XXX We need to do something with the DC if the surface gets lost. */
860 HRESULT WINAPI
861 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
863 DDSURFACEDESC2 ddsd;
864 HRESULT hr;
865 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
867 TRACE("(%p)->(%p)\n",This,phDC);
868 CHECK_LOST(This);
870 LOCK_OBJECT(This);
872 if (This->dc_in_use)
874 UNLOCK_OBJECT(This);
875 return DDERR_DCALREADYCREATED;
878 /* Lock as per MSDN.
879 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
880 * thread has it locked, but GetDC does not. */
881 ddsd.dwSize = sizeof(ddsd);
882 hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
883 if (FAILED(hr))
885 UNLOCK_OBJECT(This);
886 return hr;
889 hr = This->get_dc(This, &This->hDC);
890 if (SUCCEEDED(hr))
892 TRACE("returning %p\n",This->hDC);
894 *phDC = This->hDC;
895 This->dc_in_use = TRUE;
897 else WARN("No DC! Prepare for trouble\n");
899 UNLOCK_OBJECT(This);
900 return hr;
903 HRESULT WINAPI
904 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
906 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
908 TRACE("(%p)->(%p)\n",This,pDD);
909 *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
910 IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
911 return DD_OK;
914 HRESULT WINAPI
915 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
917 /* XXX: DDERR_INVALIDSURFACETYPE */
919 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
920 switch (dwFlags)
922 case DDGFS_CANFLIP:
923 case DDGFS_ISFLIPDONE:
924 return DD_OK;
926 default:
927 return DDERR_INVALIDPARAMS;
931 HRESULT WINAPI
932 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
934 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
936 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
937 CHECK_TEXTURE(This);
939 *pdwMaxLOD = This->max_lod;
940 return DD_OK;
943 HRESULT WINAPI
944 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
945 LPLONG pX, LPLONG pY)
947 return DDERR_NOTAOVERLAYSURFACE;
950 HRESULT WINAPI
951 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
952 LPDIRECTDRAWPALETTE* ppPalette)
954 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
956 TRACE("(%p)->(%p)\n",This,ppPalette);
957 if (This->palette == NULL)
958 return DDERR_NOPALETTEATTACHED;
960 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
961 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
962 IDirectDrawPalette));
963 return DD_OK;
966 HRESULT WINAPI
967 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
968 LPDDPIXELFORMAT pDDPixelFormat)
970 /* What is DDERR_INVALIDSURFACETYPE for here? */
971 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
973 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
974 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
975 return DD_OK;
978 HRESULT WINAPI
979 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
980 LPDWORD pdwPriority)
982 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
984 TRACE("(%p)->(%p)\n",This,pdwPriority);
985 CHECK_TEXTURE(This);
987 *pdwPriority = This->priority;
988 return DD_OK;
991 HRESULT WINAPI
992 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
993 REFGUID tag, LPVOID pBuffer,
994 LPDWORD pcbBufferSize)
996 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
997 PrivateData* data;
999 data = find_private_data(This, tag);
1000 if (data == NULL) return DDERR_NOTFOUND;
1002 /* This may not be right. */
1003 if ((data->flags & DDSPD_VOLATILE)
1004 && data->uniqueness_value != This->uniqueness_value)
1005 return DDERR_EXPIRED;
1007 if (*pcbBufferSize < data->size)
1009 *pcbBufferSize = data->size;
1010 return DDERR_MOREDATA;
1013 if (data->flags & DDSPD_IUNKNOWNPTR)
1015 *(LPUNKNOWN *)pBuffer = data->ptr.object;
1016 IUnknown_AddRef(data->ptr.object);
1018 else
1020 memcpy(pBuffer, data->ptr.data, data->size);
1023 return DD_OK;
1026 HRESULT WINAPI
1027 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
1028 LPDDSURFACEDESC2 pDDSD)
1030 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1032 TRACE("(%p)->(%p)\n",This,pDDSD);
1033 if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
1034 (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
1035 ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
1036 return DDERR_GENERIC;
1039 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
1040 if (TRACE_ON(ddraw)) {
1041 DDRAW_dump_surface_desc(pDDSD);
1043 return DD_OK;
1046 HRESULT WINAPI
1047 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
1048 LPDWORD pValue)
1050 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1052 TRACE("(%p)->(%p)\n",This,pValue);
1053 *pValue = This->uniqueness_value;
1054 return DD_OK;
1057 HRESULT WINAPI
1058 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
1059 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
1061 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
1062 return DDERR_ALREADYINITIALIZED;
1065 HRESULT WINAPI
1066 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
1068 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1070 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
1071 return This->lost ? DDERR_SURFACELOST : DD_OK;
1075 /* XXX This doesn't actually do any locking or keep track of the locked
1076 * rectangles. The behaviour is poorly documented. */
1077 HRESULT WINAPI
1078 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
1079 LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
1081 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1083 if (TRACE_ON(ddraw)) {
1084 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
1085 TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags);
1087 if (WARN_ON(ddraw)) {
1088 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY)) {
1089 WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY));
1093 /* First, copy the Surface description */
1094 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
1096 /* Used to optimize the D3D Device locking */
1097 This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
1099 /* If asked only for a part, change the surface pointer.
1100 * (Not documented.) */
1101 if (prect != NULL) {
1102 TRACE(" lprect: %ldx%ld-%ldx%ld\n",
1103 prect->left,prect->top,prect->right,prect->bottom);
1104 /* First do some sanity checkings on the rectangle we receive.
1105 DungeonSiege seems to gives us once a very bad rectangle for example */
1106 if ((prect->top < 0) ||
1107 (prect->left < 0) ||
1108 (prect->bottom < 0) ||
1109 (prect->right < 0) ||
1110 (prect->left >= prect->right) ||
1111 (prect->top >= prect->bottom) ||
1112 (prect->left >= This->surface_desc.dwWidth) ||
1113 (prect->right > This->surface_desc.dwWidth) ||
1114 (prect->top >= This->surface_desc.dwHeight) ||
1115 (prect->bottom > This->surface_desc.dwHeight)) {
1116 ERR(" Invalid values in LPRECT !!!\n");
1117 return DDERR_INVALIDPARAMS;
1120 This->lock_update(This, prect, flags);
1122 if (pDDSD->u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
1123 int blksize;
1124 switch(pDDSD->u4.ddpfPixelFormat.dwFourCC) {
1125 case MAKE_FOURCC('D','X','T','1') : blksize = 8; break;
1126 case MAKE_FOURCC('D','X','T','3') : blksize = 16; break;
1127 case MAKE_FOURCC('D','X','T','5') : blksize = 16; break;
1128 default: return DDERR_INVALIDPIXELFORMAT;
1130 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1131 + prect->top/4 * (pDDSD->dwWidth+3)/4 * blksize
1132 + prect->left/4 * blksize;
1133 } else
1134 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1135 + prect->top * This->surface_desc.u1.lPitch
1136 + prect->left * GET_BPP(This->surface_desc);
1137 } else {
1138 This->lock_update(This, NULL, flags);
1141 TRACE("locked surface returning description : \n");
1142 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
1144 return DD_OK;
1147 HRESULT WINAPI
1148 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1150 /* Some surface types should return DDERR_CANTPAGELOCK. */
1151 return DD_OK;
1154 HRESULT WINAPI
1155 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1157 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1158 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1159 return DD_OK;
1162 HRESULT WINAPI
1163 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1165 HRESULT hr;
1166 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1168 TRACE("(%p)->(%p)\n",This,hDC);
1170 if (!This->dc_in_use || This->hDC != hDC)
1171 return DDERR_INVALIDPARAMS;
1173 This->release_dc(This, hDC);
1175 hr = IDirectDrawSurface7_Unlock(iface, NULL);
1176 if (FAILED(hr)) return hr;
1178 This->dc_in_use = FALSE;
1179 This->hDC = 0;
1181 return DD_OK;
1184 /* Restore */
1186 HRESULT WINAPI
1187 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
1188 LPDIRECTDRAWCLIPPER pDDClipper)
1190 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1192 TRACE("(%p)->(%p)\n",This,pDDClipper);
1193 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
1194 return DD_OK;
1196 if (This->clipper != NULL)
1197 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1198 IDirectDrawClipper));
1200 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1201 pDDClipper);
1202 if (pDDClipper != NULL)
1203 IDirectDrawClipper_AddRef(pDDClipper);
1205 return DD_OK;
1208 HRESULT WINAPI
1209 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
1210 DWORD dwFlags, LPDDCOLORKEY pCKey)
1212 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1214 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
1216 if (TRACE_ON(ddraw)) {
1217 TRACE(" - colorkey flags : ");
1218 DDRAW_dump_colorkeyflag(dwFlags);
1221 if ((dwFlags & DDCKEY_COLORSPACE) != 0) {
1222 FIXME(" colorkey value not supported (%08lx) !\n", dwFlags);
1223 return DDERR_INVALIDPARAMS;
1226 /* TODO: investigate if this function can take multiple bits set at the same
1227 time (ie setting multiple colorkey values at the same time with only
1228 one API call).
1230 if (pCKey) {
1231 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1232 case DDCKEY_DESTBLT:
1233 This->surface_desc.ddckCKDestBlt = *pCKey;
1234 This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
1235 break;
1237 case DDCKEY_DESTOVERLAY:
1238 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1239 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1240 break;
1242 case DDCKEY_SRCOVERLAY:
1243 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1244 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1245 break;
1247 case DDCKEY_SRCBLT:
1248 This->surface_desc.ddckCKSrcBlt = *pCKey;
1249 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
1250 break;
1252 default:
1253 return DDERR_INVALIDPARAMS;
1255 } else {
1256 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1257 case DDCKEY_DESTBLT:
1258 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
1259 break;
1261 case DDCKEY_DESTOVERLAY:
1262 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
1263 break;
1265 case DDCKEY_SRCOVERLAY:
1266 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
1267 break;
1269 case DDCKEY_SRCBLT:
1270 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
1271 break;
1273 default:
1274 return DDERR_INVALIDPARAMS;
1278 if (This->aux_setcolorkey_cb) This->aux_setcolorkey_cb(This, dwFlags, pCKey);
1280 return DD_OK;
1283 HRESULT WINAPI
1284 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1286 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1288 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1289 CHECK_TEXTURE(This);
1291 This->max_lod = dwMaxLOD;
1292 return DD_OK;
1295 HRESULT WINAPI
1296 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1297 LONG X, LONG Y)
1299 return DDERR_NOTAOVERLAYSURFACE;
1302 HRESULT WINAPI
1303 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1304 LPDIRECTDRAWPALETTE pPalette)
1306 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1307 IDirectDrawPalette *pal_to_rel = NULL;
1309 TRACE("(%p)->(%p)\n",This,pPalette);
1310 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1311 return DD_OK;
1313 if (This->palette != NULL) {
1314 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1315 This->palette->global.dwFlags &= ~DDPCAPS_PRIMARYSURFACE;
1316 pal_to_rel = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
1319 This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1320 pPalette);
1321 if (pPalette != NULL) {
1322 IDirectDrawPalette_AddRef(pPalette);
1323 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1324 This->palette->global.dwFlags |= DDPCAPS_PRIMARYSURFACE;
1327 This->set_palette(This, This->palette);
1329 /* Do the palette release at the end to prevent doing some 'loop' when removing
1330 * the surface maintaining the last reference on a palette.
1332 if (pal_to_rel != NULL)
1333 IDirectDrawPalette_Release(pal_to_rel);
1335 return DD_OK;
1338 HRESULT WINAPI
1339 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1340 DWORD dwPriority)
1342 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1344 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1345 CHECK_TEXTURE(This);
1347 This->priority = dwPriority;
1348 return DD_OK;
1351 /* Be careful when locking this: it is risky to call the object's AddRef
1352 * or Release holding a lock. */
1353 HRESULT WINAPI
1354 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1355 REFGUID tag, LPVOID pData,
1356 DWORD cbSize, DWORD dwFlags)
1358 PrivateData* data;
1359 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1361 data = find_private_data(This, tag);
1362 if (data == NULL)
1364 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1365 if (data == NULL) return DDERR_OUTOFMEMORY;
1367 data->tag = *tag;
1368 data->flags = dwFlags;
1369 data->uniqueness_value = This->uniqueness_value;
1371 if (dwFlags & DDSPD_IUNKNOWNPTR)
1373 data->ptr.object = (LPUNKNOWN)pData;
1374 data->size = sizeof(LPUNKNOWN);
1375 IUnknown_AddRef(data->ptr.object);
1377 else
1379 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1380 if (data->ptr.data == NULL)
1382 HeapFree(GetProcessHeap(), 0, data);
1383 return DDERR_OUTOFMEMORY;
1387 /* link it in */
1388 data->next = This->private_data;
1389 data->prev = NULL;
1390 if (This->private_data)
1391 This->private_data->prev = data;
1392 This->private_data = data;
1394 return DD_OK;
1396 else
1398 /* I don't actually know how windows handles this case. The only
1399 * reason I don't just call FreePrivateData is because I want to
1400 * guarantee SetPrivateData working when using LPUNKNOWN or data
1401 * that is no larger than the old data. */
1403 return E_FAIL;
1407 /* SetSurfaceDesc */
1409 HRESULT WINAPI
1410 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1412 ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1414 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1416 This->unlock_update(This, pRect);
1417 if (This->aux_unlock)
1418 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1420 return DD_OK;
1423 HRESULT WINAPI
1424 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1425 LPRECT pSrcRect,
1426 LPDIRECTDRAWSURFACE7 pDstSurface,
1427 LPRECT pDstRect, DWORD dwFlags,
1428 LPDDOVERLAYFX pFX)
1430 return DDERR_UNSUPPORTED;
1433 /* MSDN: "not currently implemented." */
1434 HRESULT WINAPI
1435 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1436 DWORD dwFlags)
1438 return DDERR_UNSUPPORTED;
1441 HRESULT WINAPI
1442 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1443 DWORD dwFlags,
1444 LPDIRECTDRAWSURFACE7 pDDSRef)
1446 return DDERR_NOTAOVERLAYSURFACE;