- fix small TRACE bug introduced in a previous patch
[wine.git] / dlls / ddraw / dsurface / main.c
blobcfaac3f47874c03bc50fa530519020a0e4949542
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"
22 #include "winerror.h"
24 #include <assert.h>
25 #include <string.h>
27 #include "mesa_private.h"
28 #include "wine/debug.h"
29 #include "ddraw_private.h"
30 #include "dsurface/main.h"
31 #include "ddraw/main.h"
32 #include "dsurface/thunks.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
36 /** Creation/Destruction functions */
38 HRESULT
39 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
40 IDirectDrawImpl *pDD,
41 const DDSURFACEDESC2 *pDDSD)
43 TRACE("(%p)->(%p,%p)\n", This, pDD, pDDSD);
45 if (pDDSD != &This->surface_desc) {
46 This->surface_desc.dwSize = sizeof(This->surface_desc);
47 DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
49 This->uniqueness_value = 1; /* unchecked */
50 This->ref = 1;
52 This->local.lpSurfMore = &This->more;
53 This->local.lpGbl = &This->global;
54 This->local.dwProcessId = GetCurrentProcessId();
55 This->local.dwFlags = 0; /* FIXME */
56 This->local.ddsCaps.dwCaps = This->surface_desc.ddsCaps.dwCaps;
57 /* FIXME: more local stuff */
58 This->more.lpDD_lcl = &pDD->local;
59 This->more.ddsCapsEx.dwCaps2 = This->surface_desc.ddsCaps.dwCaps2;
60 This->more.ddsCapsEx.dwCaps3 = This->surface_desc.ddsCaps.dwCaps3;
61 This->more.ddsCapsEx.dwCaps4 = This->surface_desc.ddsCaps.dwCaps4;
62 /* FIXME: more more stuff */
63 This->gmore = &This->global_more;
64 This->global.u3.lpDD = pDD->local.lpGbl;
65 /* FIXME: more global stuff */
67 This->final_release = Main_DirectDrawSurface_final_release;
68 This->late_allocate = Main_DirectDrawSurface_late_allocate;
69 This->attach = Main_DirectDrawSurface_attach;
70 This->detach = Main_DirectDrawSurface_detach;
71 This->lock_update = Main_DirectDrawSurface_lock_update;
72 This->unlock_update = Main_DirectDrawSurface_unlock_update;
73 This->lose_surface = Main_DirectDrawSurface_lose_surface;
74 This->set_palette = Main_DirectDrawSurface_set_palette;
75 This->update_palette = Main_DirectDrawSurface_update_palette;
76 This->get_display_window = Main_DirectDrawSurface_get_display_window;
77 This->get_gamma_ramp = Main_DirectDrawSurface_get_gamma_ramp;
78 This->set_gamma_ramp = Main_DirectDrawSurface_set_gamma_ramp;
80 ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
81 DDRAW_IDDS3_Thunk_VTable);
82 ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
83 DDRAW_IDDGC_VTable);
85 /* There is no generic implementation of IDDS7 or texture */
87 Main_DirectDraw_AddSurface(pDD, This);
88 return DD_OK;
91 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
93 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
96 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
98 return DD_OK;
101 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
103 This->final_release(This);
104 if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
105 if (This->tex_private) HeapFree(GetProcessHeap(), 0, This->tex_private);
106 HeapFree(GetProcessHeap(), 0, This);
109 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
111 WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
112 Main_DirectDrawSurface_Destroy(This);
115 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
117 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
119 TRACE("(%p)->(): decreasing from %ld\n", This, This->ref);
121 if (--This->ref == 0)
123 if (This->aux_release)
124 This->aux_release(This->aux_ctx, This->aux_data);
125 Main_DirectDrawSurface_Destroy(This);
127 TRACE("released surface %p\n", This);
129 return 0;
132 return This->ref;
135 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
137 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
139 TRACE("(%p)->(): increasing from %ld\n", This, This->ref);
141 return ++This->ref;
144 HRESULT WINAPI
145 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
146 LPVOID* ppObj)
148 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
149 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
151 *ppObj = NULL;
153 if (IsEqualGUID(&IID_IUnknown, riid)
154 || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
155 || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
157 This->ref++;
158 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
159 return S_OK;
161 else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
162 || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
163 || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
165 This->ref++;
166 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
167 return S_OK;
169 else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
171 This->ref++;
172 *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
173 return S_OK;
175 #ifdef HAVE_OPENGL
176 else if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL, riid ) ||
177 IsEqualGUID( &IID_IDirect3DHALDevice, riid) )
179 IDirect3DDeviceImpl *d3ddevimpl;
180 HRESULT ret_value;
182 ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner->d3d, This);
183 if (FAILED(ret_value)) return ret_value;
185 *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
186 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj);
188 This->ref++; /* No idea if this is correct.. Need to check using real Windows */
189 return ret_value;
191 else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
192 IsEqualGUID( &IID_IDirect3DTexture2, riid ))
194 HRESULT ret_value = S_OK;
196 /* In case the texture surface was created before the D3D creation */
197 if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) == 0) return E_NOINTERFACE;
198 /* Create a 'delayed' private field only if it is not an offscreen texture... */
199 if (This->tex_private == NULL) {
200 if (This->ddraw_owner->d3d == NULL) {
201 ERR("Texture created with no D3D object yet.. Not supported !\n");
202 return E_NOINTERFACE;
205 if (((This->surface_desc.dwFlags & DDSD_MIPMAPCOUNT) &&
206 (This->surface_desc.u2.dwMipMapCount > 1)) ||
207 (This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)) {
208 ERR(" need to fix mipmaping in this case !!\n");
211 ret_value = This->ddraw_owner->d3d->create_texture(This->ddraw_owner->d3d, This, FALSE, NULL, 0);
212 if (FAILED(ret_value)) return ret_value;
214 if (IsEqualGUID( &IID_IDirect3DTexture, riid )) {
215 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture);
216 TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj);
217 } else {
218 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture2);
219 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj);
221 This->ref++;
222 return ret_value;
224 #endif
226 return E_NOINTERFACE;
229 /*** Callbacks */
231 BOOL
232 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
233 IDirectDrawSurfaceImpl *to)
235 return TRUE;
238 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
240 return TRUE;
243 void
244 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
245 DWORD dwFlags)
249 void
250 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
251 LPCRECT pRect)
255 void
256 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
260 void
261 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
262 IDirectDrawPaletteImpl* pal)
266 void
267 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
268 IDirectDrawPaletteImpl* pal,
269 DWORD dwStart, DWORD dwCount,
270 LPPALETTEENTRY palent)
274 HWND
275 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
277 return 0;
280 HRESULT
281 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
282 DWORD dwFlags,
283 LPDDGAMMARAMP lpGammaRamp)
285 HDC hDC;
286 HRESULT hr;
287 hr = This->get_dc(This, &hDC);
288 if (FAILED(hr)) return hr;
289 hr = GetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
290 This->release_dc(This, hDC);
291 return hr;
294 HRESULT
295 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
296 DWORD dwFlags,
297 LPDDGAMMARAMP lpGammaRamp)
299 HDC hDC;
300 HRESULT hr;
301 hr = This->get_dc(This, &hDC);
302 if (FAILED(hr)) return hr;
303 hr = SetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
304 This->release_dc(This, hDC);
305 return hr;
309 /*** Interface functions */
311 HRESULT WINAPI
312 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
313 LPDIRECTDRAWSURFACE7 pAttach)
315 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
316 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
317 IDirectDrawSurface7, pAttach);
319 TRACE("(%p)->(%p)\n",This,pAttach);
321 /* Does windows check this? */
322 if (surf == This)
323 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
325 /* Does windows check this? */
326 if (surf->ddraw_owner != This->ddraw_owner)
327 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
329 if (surf->surface_owner != NULL)
330 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
332 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
333 * But apparently backbuffers and mipmaps can be attached too. */
335 /* Set MIPMAPSUBLEVEL if this seems to be one */
336 if (This->surface_desc.ddsCaps.dwCaps &
337 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
338 surf->surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
339 /* FIXME: we should probably also add to dwMipMapCount of this
340 * and all parent surfaces (update create_texture if you do) */
343 /* Callback to allow the surface to do something special now that it is
344 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
345 if (!surf->attach(surf, This))
346 return DDERR_CANNOTATTACHSURFACE;
348 /* check: Where should it go in the chain? This puts it on the head. */
349 if (This->attached)
350 This->attached->prev_attached = surf;
351 surf->next_attached = This->attached;
352 surf->prev_attached = NULL;
353 This->attached = surf;
354 surf->surface_owner = This;
356 IDirectDrawSurface7_AddRef(pAttach);
358 return DD_OK;
361 /* MSDN: "not currently implemented." */
362 HRESULT WINAPI
363 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
364 LPRECT pRect)
366 TRACE("(%p)->(%p)\n",iface,pRect);
367 return DDERR_UNSUPPORTED; /* unchecked */
370 /* MSDN: "not currently implemented." */
371 HRESULT WINAPI
372 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
373 LPDDBLTBATCH pBatch, DWORD dwCount,
374 DWORD dwFlags)
376 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
377 return DDERR_UNSUPPORTED; /* unchecked */
380 HRESULT WINAPI
381 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
383 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
384 volatile IDirectDrawSurfaceImpl* vThis = This;
386 TRACE("(%p)\n",This);
387 /* A uniquness value of 0 is apparently special.
388 * This needs to be checked. */
389 while (1)
391 DWORD old_uniqueness_value = vThis->uniqueness_value;
392 DWORD new_uniqueness_value = old_uniqueness_value+1;
394 if (old_uniqueness_value == 0) break;
395 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
397 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
398 old_uniqueness_value,
399 new_uniqueness_value)
400 == old_uniqueness_value)
401 break;
404 return DD_OK;
407 HRESULT WINAPI
408 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
409 DWORD dwFlags,
410 LPDIRECTDRAWSURFACE7 pAttach)
412 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
413 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
414 IDirectDrawSurface7, pAttach);
416 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
418 if (!surf || (surf->surface_owner != This))
419 return DDERR_SURFACENOTATTACHED; /* unchecked */
421 surf->detach(surf);
423 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
424 if (This->surface_desc.ddsCaps.dwCaps &
425 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
426 surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
427 /* FIXME: we should probably also subtract from dwMipMapCount of this
428 * and all parent surfaces */
431 if (surf->next_attached)
432 surf->next_attached->prev_attached = surf->prev_attached;
433 if (surf->prev_attached)
434 surf->prev_attached->next_attached = surf->next_attached;
435 if (This->attached == surf)
436 This->attached = surf->next_attached;
438 IDirectDrawSurface7_Release(pAttach);
440 return DD_OK;
443 HRESULT WINAPI
444 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
445 LPVOID context,
446 LPDDENUMSURFACESCALLBACK7 cb)
448 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
449 IDirectDrawSurfaceImpl* surf;
451 TRACE("(%p)->(%p,%p)\n",This,context,cb);
453 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
455 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
456 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
457 context) == DDENUMRET_CANCEL)
458 break;
461 return DD_OK;
464 HRESULT WINAPI
465 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
466 DWORD dwFlags, LPVOID context,
467 LPDDENUMSURFACESCALLBACK7 cb)
469 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
470 return DD_OK;
473 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
474 IDirectDrawSurfaceImpl* back,
475 DWORD dwFlags)
477 /* uniqueness_value? */
478 /* This is necessary. But is it safe? */
480 HDC tmp = front->hDC;
481 front->hDC = back->hDC;
482 back->hDC = tmp;
486 BOOL tmp = front->dc_in_use;
487 front->dc_in_use = back->dc_in_use;
488 back->dc_in_use = tmp;
492 FLATPTR tmp = front->global.fpVidMem;
493 front->global.fpVidMem = back->global.fpVidMem;
494 back->global.fpVidMem = tmp;
498 ULONG_PTR tmp = front->global_more.hKernelSurface;
499 front->global_more.hKernelSurface = back->global_more.hKernelSurface;
500 back->global_more.hKernelSurface = tmp;
503 return TRUE;
506 HRESULT WINAPI
507 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
508 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
510 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
511 IDirectDrawSurfaceImpl* target;
512 HRESULT hr;
514 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
516 /* MSDN: "This method can be called only for a surface that has the
517 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
518 if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
519 != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
520 return DDERR_NOTFLIPPABLE;
522 if (This->aux_flip)
523 if (This->aux_flip(This->aux_ctx, This->aux_data))
524 return DD_OK;
526 /* 1. find the flip target */
527 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
528 if (override == NULL)
530 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
531 LPDIRECTDRAWSURFACE7 tgt;
533 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
534 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
536 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
537 tgt);
538 IDirectDrawSurface7_Release(tgt);
540 else
542 BOOL on_chain = FALSE;
543 IDirectDrawSurfaceImpl* surf;
545 /* MSDN: "The method fails if the specified [override] surface is not
546 * a member of the flipping chain." */
548 /* Verify that override is on this flip chain. We assume that
549 * surf is the head of the flipping chain, because it's the front
550 * buffer. */
551 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
552 override);
554 /* Either target is (indirectly) attached to This or This is
555 * (indirectly) attached to target. */
556 for (surf = target; surf != NULL; surf = surf->surface_owner)
558 if (surf == This)
560 on_chain = TRUE;
561 break;
565 if (!on_chain)
566 return DDERR_INVALIDPARAMS; /* unchecked */
569 TRACE("flip to backbuffer: %p\n",target);
570 if (This->flip_data(This, target, dwFlags))
571 This->flip_update(This, dwFlags);
573 return DD_OK;
576 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
577 REFGUID tag)
579 PrivateData* data;
580 for (data = This->private_data; data != NULL; data = data->next)
582 if (IsEqualGUID(&data->tag, tag)) break;
585 return data;
588 HRESULT WINAPI
589 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
591 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
592 PrivateData *data;
594 data = find_private_data(This, tag);
595 if (data == NULL) return DDERR_NOTFOUND;
597 if (data->prev)
598 data->prev->next = data->next;
599 if (data->next)
600 data->next->prev = data->prev;
602 if (data->flags & DDSPD_IUNKNOWNPTR)
604 if (data->ptr.object != NULL)
605 IUnknown_Release(data->ptr.object);
607 else
608 HeapFree(GetProcessHeap(), 0, data->ptr.data);
610 HeapFree(GetProcessHeap(), 0, data);
612 return DD_OK;
615 HRESULT WINAPI
616 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
617 LPDDSCAPS2 pCaps,
618 LPDIRECTDRAWSURFACE7* ppSurface)
620 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
621 IDirectDrawSurfaceImpl* surf;
622 IDirectDrawSurfaceImpl* found = NULL;
623 DDSCAPS2 our_caps;
625 if (TRACE_ON(ddraw)) {
626 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
627 pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
628 DPRINTF(" Caps are : "); DDRAW_dump_DDSCAPS2(pCaps); DPRINTF("\n");
631 our_caps = *pCaps;
632 if ((This->ddraw_owner->local.dwLocalFlags & DDRAWILCL_DIRECTDRAW7) == 0) {
633 /* As this is not a DirectDraw7 application, remove the garbage that some games
634 put in the new fields of the DDSCAPS2 structure. */
635 our_caps.dwCaps2 = 0;
636 our_caps.dwCaps3 = 0;
637 our_caps.dwCaps4 = 0;
638 if (TRACE_ON(ddraw)) {
639 DPRINTF(" Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps); DPRINTF("\n");
643 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
645 if (TRACE_ON(ddraw)) {
646 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
647 surf->surface_desc.ddsCaps.dwCaps,
648 surf->surface_desc.ddsCaps.dwCaps2,
649 surf->surface_desc.ddsCaps.dwCaps3,
650 surf->surface_desc.ddsCaps.dwCaps4);
651 DPRINTF(" Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf->surface_desc.ddsCaps)); DPRINTF("\n");
653 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
654 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2))
656 /* MSDN: "This method fails if more than one surface is attached
657 * that matches the capabilities requested." */
658 if (found != NULL)
660 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
661 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
662 to be correct, given what 3DMark expects from MipMapped surfaces.
663 We shall just continue instead. */
666 found = surf;
670 if (found == NULL) {
671 TRACE("Did not find any valid surface\n");
672 return DDERR_NOTFOUND;
675 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
677 if (TRACE_ON(ddraw)) {
678 TRACE("Returning surface %p with description : \n", *ppSurface);
679 DDRAW_dump_surface_desc(&(found->surface_desc));
682 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
683 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
684 return DD_OK;
687 HRESULT WINAPI
688 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
690 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
692 switch (dwFlags)
694 case DDGBS_CANBLT:
695 case DDGBS_ISBLTDONE:
696 return DD_OK;
698 default:
699 return DDERR_INVALIDPARAMS;
703 HRESULT WINAPI
704 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
706 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
708 TRACE("(%p)->(%p)\n",This,pCaps);
709 *pCaps = This->surface_desc.ddsCaps;
710 return DD_OK;
713 HRESULT WINAPI
714 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
715 LPDIRECTDRAWCLIPPER* ppClipper)
717 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
719 TRACE("(%p)->(%p)\n",This,ppClipper);
720 if (This->clipper == NULL)
721 return DDERR_NOCLIPPERATTACHED;
723 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
724 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
725 IDirectDrawClipper));
726 return DD_OK;
729 HRESULT WINAPI
730 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
731 LPDDCOLORKEY pCKey)
733 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
734 * isn't there? That's like saying that an int isn't there. (Which MS
735 * has done in other docs.) */
737 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
739 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
740 switch (dwFlags)
742 case DDCKEY_DESTBLT:
743 *pCKey = This->surface_desc.ddckCKDestBlt;
744 break;
746 case DDCKEY_DESTOVERLAY:
747 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
748 break;
750 case DDCKEY_SRCBLT:
751 *pCKey = This->surface_desc.ddckCKSrcBlt;
752 break;
754 case DDCKEY_SRCOVERLAY:
755 *pCKey = This->surface_desc.ddckCKSrcOverlay;
756 break;
758 default:
759 return DDERR_INVALIDPARAMS;
762 return DD_OK;
765 /* XXX We need to do something with the DC if the surface gets lost. */
766 HRESULT WINAPI
767 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
769 DDSURFACEDESC2 ddsd;
770 HRESULT hr;
771 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
773 TRACE("(%p)->(%p)\n",This,phDC);
774 CHECK_LOST(This);
776 LOCK_OBJECT(This);
778 if (This->dc_in_use)
780 UNLOCK_OBJECT(This);
781 return DDERR_DCALREADYCREATED;
784 /* Lock as per MSDN.
785 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
786 * thread has it locked, but GetDC does not. */
787 ddsd.dwSize = sizeof(ddsd);
788 hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, DDLOCK_READONLY, 0);
789 if (FAILED(hr))
791 UNLOCK_OBJECT(This);
792 return hr;
795 hr = This->get_dc(This, &This->hDC);
796 if (SUCCEEDED(hr))
798 TRACE("returning %p\n",This->hDC);
800 *phDC = This->hDC;
801 This->dc_in_use = TRUE;
803 else WARN("No DC! Prepare for trouble\n");
805 UNLOCK_OBJECT(This);
806 return hr;
809 HRESULT WINAPI
810 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
812 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
814 TRACE("(%p)->(%p)\n",This,pDD);
815 *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
816 IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
817 return DD_OK;
820 HRESULT WINAPI
821 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
823 /* XXX: DDERR_INVALIDSURFACETYPE */
825 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
826 switch (dwFlags)
828 case DDGFS_CANFLIP:
829 case DDGFS_ISFLIPDONE:
830 return DD_OK;
832 default:
833 return DDERR_INVALIDPARAMS;
837 HRESULT WINAPI
838 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
840 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
842 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
843 CHECK_TEXTURE(This);
845 *pdwMaxLOD = This->max_lod;
846 return DD_OK;
849 HRESULT WINAPI
850 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
851 LPLONG pX, LPLONG pY)
853 return DDERR_NOTAOVERLAYSURFACE;
856 HRESULT WINAPI
857 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
858 LPDIRECTDRAWPALETTE* ppPalette)
860 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
862 TRACE("(%p)->(%p)\n",This,ppPalette);
863 if (This->palette == NULL)
864 return DDERR_NOPALETTEATTACHED;
866 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
867 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
868 IDirectDrawPalette));
869 return DD_OK;
872 HRESULT WINAPI
873 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
874 LPDDPIXELFORMAT pDDPixelFormat)
876 /* What is DDERR_INVALIDSURFACETYPE for here? */
877 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
879 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
880 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
881 return DD_OK;
884 HRESULT WINAPI
885 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
886 LPDWORD pdwPriority)
888 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
890 TRACE("(%p)->(%p)\n",This,pdwPriority);
891 CHECK_TEXTURE(This);
893 *pdwPriority = This->priority;
894 return DD_OK;
897 HRESULT WINAPI
898 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
899 REFGUID tag, LPVOID pBuffer,
900 LPDWORD pcbBufferSize)
902 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
903 PrivateData* data;
905 data = find_private_data(This, tag);
906 if (data == NULL) return DDERR_NOTFOUND;
908 /* This may not be right. */
909 if ((data->flags & DDSPD_VOLATILE)
910 && data->uniqueness_value != This->uniqueness_value)
911 return DDERR_EXPIRED;
913 if (*pcbBufferSize < data->size)
915 *pcbBufferSize = data->size;
916 return DDERR_MOREDATA;
919 if (data->flags & DDSPD_IUNKNOWNPTR)
921 *(LPUNKNOWN *)pBuffer = data->ptr.object;
922 IUnknown_AddRef(data->ptr.object);
924 else
926 memcpy(pBuffer, data->ptr.data, data->size);
929 return DD_OK;
932 HRESULT WINAPI
933 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
934 LPDDSURFACEDESC2 pDDSD)
936 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
938 TRACE("(%p)->(%p)\n",This,pDDSD);
939 if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
940 (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
941 ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
942 return DDERR_GENERIC;
945 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
946 if (TRACE_ON(ddraw)) {
947 DDRAW_dump_surface_desc(pDDSD);
949 return DD_OK;
952 HRESULT WINAPI
953 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
954 LPDWORD pValue)
956 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
958 TRACE("(%p)->(%p)\n",This,pValue);
959 *pValue = This->uniqueness_value;
960 return DD_OK;
963 HRESULT WINAPI
964 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
965 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
967 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
968 return DDERR_ALREADYINITIALIZED;
971 HRESULT WINAPI
972 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
974 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
976 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
977 return This->lost ? DDERR_SURFACELOST : DD_OK;
981 /* XXX This doesn't actually do any locking or keep track of the locked
982 * rectangles. The behaviour is poorly documented. */
983 HRESULT WINAPI
984 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
985 LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
987 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
989 if (TRACE_ON(ddraw)) {
990 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
991 TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags);
993 if (WARN_ON(ddraw)) {
994 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY)) {
995 WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY));
999 /* First, copy the Surface description */
1000 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
1002 TRACE("locked surface returning description : \n");
1003 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
1005 /* Used to optimize the D3D Device locking */
1006 This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
1008 /* If asked only for a part, change the surface pointer.
1009 * (Not documented.) */
1010 if (prect != NULL) {
1011 TRACE(" lprect: %dx%d-%dx%d\n",
1012 prect->top,prect->left,prect->bottom,prect->right
1014 if ((prect->top < 0) ||
1015 (prect->left < 0) ||
1016 (prect->bottom < 0) ||
1017 (prect->right < 0)) {
1018 ERR(" Negative values in LPRECT !!!\n");
1019 return DDERR_INVALIDPARAMS;
1022 This->lock_update(This, prect, flags);
1024 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1025 + prect->top * This->surface_desc.u1.lPitch
1026 + prect->left * GET_BPP(This->surface_desc);
1027 } else {
1028 This->lock_update(This, NULL, flags);
1031 return DD_OK;
1034 HRESULT WINAPI
1035 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1037 /* Some surface types should return DDERR_CANTPAGELOCK. */
1038 return DD_OK;
1041 HRESULT WINAPI
1042 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1044 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1045 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1046 return DD_OK;
1049 HRESULT WINAPI
1050 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1052 HRESULT hr;
1053 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1055 TRACE("(%p)->(%p)\n",This,hDC);
1057 if (!This->dc_in_use || This->hDC != hDC)
1058 return DDERR_INVALIDPARAMS;
1060 This->release_dc(This, hDC);
1062 hr = IDirectDrawSurface7_Unlock(iface, NULL);
1063 if (FAILED(hr)) return hr;
1065 This->dc_in_use = FALSE;
1066 This->hDC = 0;
1068 return DD_OK;
1071 /* Restore */
1073 HRESULT WINAPI
1074 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
1075 LPDIRECTDRAWCLIPPER pDDClipper)
1077 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1079 TRACE("(%p)->(%p)\n",This,pDDClipper);
1080 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
1081 return DD_OK;
1083 if (This->clipper != NULL)
1084 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1085 IDirectDrawClipper));
1087 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1088 pDDClipper);
1089 if (pDDClipper != NULL)
1090 IDirectDrawClipper_AddRef(pDDClipper);
1092 return DD_OK;
1095 HRESULT WINAPI
1096 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
1097 DWORD dwFlags, LPDDCOLORKEY pCKey)
1099 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1101 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
1102 if (pCKey == NULL)
1104 FIXME("supposedly removing color key %lu\n",
1105 dwFlags & ~DDCKEY_COLORSPACE);
1106 return DD_OK;
1109 switch (dwFlags & ~DDCKEY_COLORSPACE)
1111 case DDCKEY_DESTBLT:
1112 This->surface_desc.ddckCKDestBlt = *pCKey;
1113 break;
1115 case DDCKEY_DESTOVERLAY:
1116 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1117 break;
1119 case DDCKEY_SRCOVERLAY:
1120 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1121 break;
1123 case DDCKEY_SRCBLT:
1124 This->surface_desc.ddckCKSrcBlt = *pCKey;
1125 break;
1127 default:
1128 return DDERR_INVALIDPARAMS;
1131 return DD_OK;
1134 HRESULT WINAPI
1135 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1137 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1139 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1140 CHECK_TEXTURE(This);
1142 This->max_lod = dwMaxLOD;
1143 return DD_OK;
1146 HRESULT WINAPI
1147 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1148 LONG X, LONG Y)
1150 return DDERR_NOTAOVERLAYSURFACE;
1153 HRESULT WINAPI
1154 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1155 LPDIRECTDRAWPALETTE pPalette)
1157 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1159 TRACE("(%p)->(%p)\n",This,pPalette);
1160 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1161 return DD_OK;
1163 if (This->palette != NULL) {
1164 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1165 This->palette->global.dwFlags &= ~DDPCAPS_PRIMARYSURFACE;
1166 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette,
1167 IDirectDrawPalette));
1170 This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1171 pPalette);
1172 if (pPalette != NULL) {
1173 IDirectDrawPalette_AddRef(pPalette);
1174 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1175 This->palette->global.dwFlags |= DDPCAPS_PRIMARYSURFACE;
1178 This->set_palette(This, This->palette);
1180 return DD_OK;
1183 HRESULT WINAPI
1184 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1185 DWORD dwPriority)
1187 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1189 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1190 CHECK_TEXTURE(This);
1192 This->priority = dwPriority;
1193 return DD_OK;
1196 /* Be careful when locking this: it is risky to call the object's AddRef
1197 * or Release holding a lock. */
1198 HRESULT WINAPI
1199 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1200 REFGUID tag, LPVOID pData,
1201 DWORD cbSize, DWORD dwFlags)
1203 PrivateData* data;
1204 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1206 data = find_private_data(This, tag);
1207 if (data == NULL)
1209 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1210 if (data == NULL) return DDERR_OUTOFMEMORY;
1212 data->tag = *tag;
1213 data->flags = dwFlags;
1214 data->uniqueness_value = This->uniqueness_value;
1216 if (dwFlags & DDSPD_IUNKNOWNPTR)
1218 data->ptr.object = (LPUNKNOWN)pData;
1219 data->size = sizeof(LPUNKNOWN);
1220 IUnknown_AddRef(data->ptr.object);
1222 else
1224 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1225 if (data->ptr.data == NULL)
1227 HeapFree(GetProcessHeap(), 0, data);
1228 return DDERR_OUTOFMEMORY;
1232 /* link it in */
1233 data->next = This->private_data;
1234 data->prev = NULL;
1235 if (This->private_data)
1236 This->private_data->prev = data;
1237 This->private_data = data;
1239 return DD_OK;
1241 else
1243 /* I don't actually know how windows handles this case. The only
1244 * reason I don't just call FreePrivateData is because I want to
1245 * guarantee SetPrivateData working when using LPUNKNOWN or data
1246 * that is no larger than the old data. */
1248 return E_FAIL;
1252 /* SetSurfaceDesc */
1254 HRESULT WINAPI
1255 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1257 ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1259 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1261 This->unlock_update(This, pRect);
1262 if (This->aux_unlock)
1263 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1265 return DD_OK;
1268 HRESULT WINAPI
1269 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1270 LPRECT pSrcRect,
1271 LPDIRECTDRAWSURFACE7 pDstSurface,
1272 LPRECT pDstRect, DWORD dwFlags,
1273 LPDDOVERLAYFX pFX)
1275 return DDERR_UNSUPPORTED;
1278 /* MSDN: "not currently implemented." */
1279 HRESULT WINAPI
1280 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1281 DWORD dwFlags)
1283 return DDERR_UNSUPPORTED;
1286 HRESULT WINAPI
1287 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1288 DWORD dwFlags,
1289 LPDIRECTDRAWSURFACE7 pDDSRef)
1291 return DDERR_NOTAOVERLAYSURFACE;