Added the DFCS_{HOT,TRANSPARENT} definitions.
[wine/gsoc_dplay.git] / dlls / ddraw / dsurface / user.c
blob3c01f3eda9562601186fe957bd39e0a3b5377d04
1 /* User-based primary surface driver
3 * Copyright 2000-2001 TransGaming Technologies Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "config.h"
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include "winerror.h"
27 #include "wine/debug.h"
28 #include "ddraw_private.h"
29 #include "dsurface/main.h"
30 #include "dsurface/dib.h"
31 #include "dsurface/user.h"
32 #include "dsurface/wndproc.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
36 /* if you use OWN_WINDOW, don't use SYNC_UPDATE, or you may get trouble */
37 /* #define SYNC_UPDATE */
38 #define OWN_WINDOW
40 #ifdef OWN_WINDOW
41 static void User_create_own_window(IDirectDrawSurfaceImpl* This);
42 static void User_destroy_own_window(IDirectDrawSurfaceImpl* This);
43 #endif
44 #ifndef SYNC_UPDATE
45 static DWORD CALLBACK User_update_thread(LPVOID);
46 #endif
47 static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc);
48 static void User_copy_from_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc);
50 static HWND get_display_window(IDirectDrawSurfaceImpl* This, LPPOINT pt);
52 static ICOM_VTABLE(IDirectDrawSurface7) User_IDirectDrawSurface7_VTable;
54 HRESULT
55 User_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
56 IDirectDrawImpl* pDD,
57 const DDSURFACEDESC2* pDDSD)
59 USER_PRIV_VAR(priv, This);
60 HRESULT hr;
62 TRACE("(%p,%p,%p)\n",This,pDD,pDDSD);
63 hr = DIB_DirectDrawSurface_Construct(This, pDD, pDDSD);
64 if (FAILED(hr)) return hr;
66 ICOM_INIT_INTERFACE(This, IDirectDrawSurface7,
67 User_IDirectDrawSurface7_VTable);
69 This->final_release = User_DirectDrawSurface_final_release;
70 This->duplicate_surface = User_DirectDrawSurface_duplicate_surface;
72 This->lock_update = User_DirectDrawSurface_lock_update;
73 This->unlock_update = User_DirectDrawSurface_unlock_update;
75 This->flip_data = User_DirectDrawSurface_flip_data;
76 This->flip_update = User_DirectDrawSurface_flip_update;
78 This->get_dc = User_DirectDrawSurface_get_dc;
79 This->release_dc = User_DirectDrawSurface_release_dc;
81 This->set_palette = User_DirectDrawSurface_set_palette;
82 This->update_palette = User_DirectDrawSurface_update_palette;
84 This->get_gamma_ramp = User_DirectDrawSurface_get_gamma_ramp;
85 This->set_gamma_ramp = User_DirectDrawSurface_set_gamma_ramp;
87 This->get_display_window = User_DirectDrawSurface_get_display_window;
89 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
91 #ifdef OWN_WINDOW
92 DirectDrawSurface_RegisterClass();
93 #endif
94 #ifndef SYNC_UPDATE
95 priv->user.update_event = CreateEventA(NULL, FALSE, FALSE, NULL);
96 priv->user.update_thread = CreateThread(NULL, 0, User_update_thread, This, 0, NULL);
97 #ifdef OWN_WINDOW
98 if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN) {
99 /* wait for window creation (or update thread destruction) */
100 while (WaitForMultipleObjects(1, &priv->user.update_thread, FALSE, 10) == WAIT_TIMEOUT)
101 if (This->more.lpDDRAWReserved) break;
102 if (!This->more.lpDDRAWReserved) {
103 ERR("window creation failed\n");
106 #endif
107 #else
108 #ifdef OWN_WINDOW
109 User_create_own_window(This);
110 #endif
111 #endif
112 if (!This->more.lpDDRAWReserved)
113 This->more.lpDDRAWReserved = (LPVOID)pDD->window;
116 return DIB_DirectDrawSurface_alloc_dc(This, &priv->user.cached_dc);
119 HRESULT
120 User_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
121 const DDSURFACEDESC2 *pDDSD,
122 LPDIRECTDRAWSURFACE7 *ppSurf,
123 IUnknown *pUnkOuter)
125 IDirectDrawSurfaceImpl* This;
126 HRESULT hr;
127 assert(pUnkOuter == NULL);
129 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
130 sizeof(*This) + sizeof(User_DirectDrawSurfaceImpl));
131 if (This == NULL) return E_OUTOFMEMORY;
133 This->private = (User_DirectDrawSurfaceImpl*)(This+1);
135 hr = User_DirectDrawSurface_Construct(This, pDD, pDDSD);
136 if (FAILED(hr))
137 HeapFree(GetProcessHeap(), 0, This);
138 else
139 *ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7);
141 return hr;
144 void User_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
146 USER_PRIV_VAR(priv, This);
148 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
150 #ifndef SYNC_UPDATE
151 HANDLE event = priv->user.update_event;
152 priv->user.update_event = 0;
153 SetEvent(event);
154 TRACE("waiting for update thread to terminate...\n");
155 #ifdef OWN_WINDOW
156 /* dispatch any waiting sendmessages */
158 MSG msg;
159 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
161 /* to avoid deadlocks, allow SendMessages from update thread
162 * through while we wait for it */
163 while (MsgWaitForMultipleObjects(1, &priv->user.update_thread, FALSE,
164 INFINITE, QS_SENDMESSAGE) == WAIT_OBJECT_0+1)
166 MSG msg;
167 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
169 #else
170 WaitForSingleObject(priv->user.update_thread,INFINITE);
171 #endif
172 TRACE("update thread terminated\n");
173 CloseHandle(priv->user.update_thread);
174 #else
175 #ifdef OWN_WINDOW
176 User_destroy_own_window(This);
177 #endif
178 #endif
179 This->more.lpDDRAWReserved = 0;
180 #ifdef OWN_WINDOW
181 DirectDrawSurface_UnregisterClass();
182 #endif
184 DIB_DirectDrawSurface_free_dc(This, priv->user.cached_dc);
185 DIB_DirectDrawSurface_final_release(This);
188 void User_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
189 LPCRECT pRect, DWORD dwFlags)
191 if (!(dwFlags & DDLOCK_WRITEONLY))
192 User_copy_from_screen(This, pRect);
194 if (pRect) {
195 This->lastlockrect = *pRect;
196 } else {
197 This->lastlockrect.left = This->lastlockrect.right = 0;
201 void User_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
202 LPCRECT pRect)
204 #ifdef SYNC_UPDATE
205 User_copy_to_screen(This, pRect);
206 #else
207 USER_PRIV_VAR(priv, This);
208 SetEvent(priv->user.update_event);
209 #endif
212 void User_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
213 IDirectDrawPaletteImpl* pal)
215 USER_PRIV_VAR(priv, This);
217 if (!pal) {
218 FIXME("selecting null palette\n");
219 /* I don't think selecting GDI object 0 will work, we should select
220 * the original palette, returned by the first SelectPalette */
221 SelectPalette(priv->user.cached_dc, 0, FALSE);
222 return;
225 SelectPalette(priv->user.cached_dc, pal->hpal, FALSE);
227 DIB_DirectDrawSurface_set_palette(This, pal);
230 void User_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
231 IDirectDrawPaletteImpl* pal,
232 DWORD dwStart, DWORD dwCount,
233 LPPALETTEENTRY palent)
235 USER_PRIV_VAR(priv, This);
237 DIB_DirectDrawSurface_update_palette(This, pal, dwStart, dwCount, palent);
238 /* FIXME: realize palette on display window */
240 #ifndef SYNC_UPDATE
241 /* with async updates, it's probably cool to force an update */
242 SetEvent(priv->user.update_event);
243 #endif
246 HRESULT User_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
247 LPDIRECTDRAWSURFACE7* ppDup)
249 return User_DirectDrawSurface_Create(This->ddraw_owner,
250 &This->surface_desc, ppDup, NULL);
253 BOOL User_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
254 IDirectDrawSurfaceImpl* back,
255 DWORD dwFlags)
257 USER_PRIV_VAR(front_priv, front);
258 USER_PRIV_VAR(back_priv, back);
261 HDC tmp;
262 tmp = front_priv->user.cached_dc;
263 front_priv->user.cached_dc = back_priv->user.cached_dc;
264 back_priv->user.cached_dc = tmp;
267 return DIB_DirectDrawSurface_flip_data(front, back, dwFlags);
270 void User_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This, DWORD dwFlags)
272 #ifdef SYNC_UPDATE
273 This->lastlockrect.left = This->lastlockrect.right = 0;
274 assert(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
275 User_copy_to_screen(This,NULL);
276 #else
277 USER_PRIV_VAR(priv, This);
278 This->lastlockrect.left = This->lastlockrect.right = 0;
279 assert(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
280 SetEvent(priv->user.update_event);
281 #endif
284 HRESULT User_DirectDrawSurface_get_dc(IDirectDrawSurfaceImpl* This, HDC* phDC)
286 USER_PRIV_VAR(priv, This);
288 *phDC = priv->user.cached_dc;
289 return S_OK;
292 HRESULT User_DirectDrawSurface_release_dc(IDirectDrawSurfaceImpl* This,
293 HDC hDC)
295 return S_OK;
298 HRESULT User_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
299 DWORD dwFlags,
300 LPDDGAMMARAMP lpGammaRamp)
302 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
304 POINT offset;
305 HWND hDisplayWnd;
306 HDC hDisplayDC;
307 HRESULT hr;
308 hDisplayWnd = get_display_window(This, &offset);
309 hDisplayDC = GetDCEx(hDisplayWnd, 0, DCX_CLIPSIBLINGS|DCX_CACHE);
310 hr = GetDeviceGammaRamp(hDisplayDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
311 ReleaseDC(hDisplayWnd, hDisplayDC);
312 return hr;
314 return Main_DirectDrawSurface_get_gamma_ramp(This, dwFlags, lpGammaRamp);
317 HRESULT User_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
318 DWORD dwFlags,
319 LPDDGAMMARAMP lpGammaRamp)
321 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
323 POINT offset;
324 HWND hDisplayWnd;
325 HDC hDisplayDC;
326 HRESULT hr;
327 hDisplayWnd = get_display_window(This, &offset);
328 hDisplayDC = GetDCEx(hDisplayWnd, 0, DCX_CLIPSIBLINGS|DCX_CACHE);
329 hr = SetDeviceGammaRamp(hDisplayDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
330 ReleaseDC(hDisplayWnd, hDisplayDC);
331 return hr;
333 return Main_DirectDrawSurface_set_gamma_ramp(This, dwFlags, lpGammaRamp);
336 /* Returns the window that hosts the display.
337 * *pt is set to the upper left position of the window relative to the
338 * upper left corner of the surface. */
339 static HWND get_display_window(IDirectDrawSurfaceImpl* This, LPPOINT pt)
341 memset(pt, 0, sizeof(*pt));
343 if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN)
345 #ifdef OWN_WINDOW
346 USER_PRIV_VAR(priv, This);
347 #if 1
348 SetWindowPos(priv->user.window, HWND_TOP, 0, 0, 0, 0,
349 SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|
350 SWP_NOREDRAW|SWP_NOSENDCHANGING|SWP_NOSIZE);
351 #endif
352 return priv->user.window;
353 #else
354 return This->ddraw_owner->window;
355 #endif
357 else
359 if (This->clipper != NULL)
361 /* looks silly, but since we don't have the clipper locked */
362 HWND hWnd = This->clipper->hWnd;
364 if (hWnd != 0)
366 ClientToScreen(hWnd, pt);
367 return hWnd;
369 else
371 static BOOL warn = 0;
372 if (!warn++) FIXME("clipper clip lists not supported\n");
374 return GetDesktopWindow();
377 else
379 static BOOL warn = 0;
380 if (!warn++) WARN("hosting on root\n");
382 return GetDesktopWindow();
387 HWND User_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
389 POINT offset;
390 return get_display_window(This, &offset);
393 #ifdef OWN_WINDOW
394 static void User_create_own_window(IDirectDrawSurfaceImpl* This)
396 USER_PRIV_VAR(priv, This);
398 if (This->ddraw_owner->cooperative_level & DDSCL_FULLSCREEN)
400 priv->user.window = CreateWindowExA(WS_EX_TOPMOST |
401 WS_EX_LAYERED |
402 WS_EX_TRANSPARENT,
403 "WINE_DDRAW", "DirectDraw",
404 WS_POPUP,
405 0, 0,
406 This->surface_desc.dwWidth,
407 This->surface_desc.dwHeight,
408 GetDesktopWindow(),
409 0, 0, This);
410 This->more.lpDDRAWReserved = (LPVOID)priv->user.window;
411 SetWindowPos(priv->user.window, HWND_TOP, 0, 0, 0, 0,
412 SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|
413 SWP_NOREDRAW|SWP_NOSENDCHANGING|SWP_NOSIZE|SWP_SHOWWINDOW);
414 UpdateWindow(priv->user.window);
418 static void User_destroy_own_window(IDirectDrawSurfaceImpl* This)
420 USER_PRIV_VAR(priv, This);
422 if (priv->user.window)
424 SetWindowPos(priv->user.window, 0, 0, 0, 0, 0,
425 SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|
426 SWP_NOREDRAW|SWP_NOSENDCHANGING|SWP_NOSIZE|SWP_HIDEWINDOW);
427 This->more.lpDDRAWReserved = NULL;
428 DestroyWindow(priv->user.window);
429 priv->user.window = 0;
432 #endif
434 #ifndef SYNC_UPDATE
435 static DWORD CALLBACK User_update_thread(LPVOID arg)
437 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)arg;
438 USER_PRIV_VAR(priv, This);
439 volatile DWORD *pActive = (volatile DWORD *)&priv->user.update_event;
440 HANDLE event = *pActive;
442 #ifdef OWN_WINDOW
443 User_create_own_window(This);
444 #endif
446 /* the point of this is that many games lock the primary surface
447 * multiple times per frame; this thread will then simply copy as
448 * often as it can without keeping the main thread waiting for
449 * each unlock, thus keeping the frame rate high */
450 do {
451 #ifdef OWN_WINDOW
452 DWORD ret = MsgWaitForMultipleObjects(1, &event, FALSE, INFINITE, QS_ALLINPUT);
453 MSG msg;
455 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
457 switch (msg.message) {
458 case WM_PAINT:
459 DispatchMessageA(&msg);
460 break;
461 default:
462 /* since we risk getting keyboard messages posted to us,
463 * repost posted messages to cooperative window */
464 PostMessageA(This->ddraw_owner->window, msg.message, msg.wParam, msg.lParam);
467 #else
468 DWORD ret = WaitForSingleObject(event, INFINITE);
469 #endif
470 if (ret == WAIT_OBJECT_0)
472 if (*pActive)
473 User_copy_to_screen(This, NULL);
474 else
475 break;
477 else if (ret != WAIT_OBJECT_0+1) break;
478 } while (TRUE);
480 #ifdef OWN_WINDOW
481 User_destroy_own_window(This);
482 #endif
484 return 0;
486 #endif
488 static void User_copy_to_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
490 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
492 POINT offset;
493 HWND hDisplayWnd;
494 HDC hDisplayDC;
495 HDC hSurfaceDC;
496 RECT drawrect;
498 if (FAILED(This->get_dc(This, &hSurfaceDC)))
499 return;
501 hDisplayWnd = get_display_window(This, &offset);
502 hDisplayDC = GetDCEx(hDisplayWnd, 0, DCX_CLIPSIBLINGS|DCX_CACHE);
503 #if 0
504 /* FIXME: this doesn't work... if users really want to run
505 * X in 8bpp, then we need to call directly into display.drv
506 * (or Wine's equivalent), and force a private colormap
507 * without default entries. */
508 if (This->palette) {
509 SelectPalette(hDisplayDC, This->palette->hpal, FALSE);
510 RealizePalette(hDisplayDC); /* sends messages => deadlocks */
512 #endif
513 drawrect.left = 0;
514 drawrect.right = This->surface_desc.dwWidth;
515 drawrect.top = 0;
516 drawrect.bottom = This->surface_desc.dwHeight;
518 if (This->clipper) {
519 RECT xrc;
520 HWND hwnd = This->clipper->hWnd;
521 if (hwnd && GetWindowRect(hwnd,&xrc)) {
522 /* Do not forget to honor the offset within the clip window. */
523 /* translate the surface to 0.0 of the clip window */
524 OffsetRect(&drawrect,offset.x,offset.y);
525 IntersectRect(&drawrect,&drawrect,&xrc);
526 /* translate it back to its original position */
527 OffsetRect(&drawrect,-offset.x,-offset.y);
530 if (rc)
531 IntersectRect(&drawrect,&drawrect,rc);
532 else {
533 /* Only use this if the caller did not pass a rectangle, since
534 * due to double locking this could be the wrong one ... */
535 if (This->lastlockrect.left != This->lastlockrect.right)
536 IntersectRect(&drawrect,&drawrect,&This->lastlockrect);
538 BitBlt(hDisplayDC,
539 drawrect.left+offset.x, drawrect.top+offset.y,
540 drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
541 hSurfaceDC,
542 drawrect.left, drawrect.top,
543 SRCCOPY
545 ReleaseDC(hDisplayWnd, hDisplayDC);
549 static void User_copy_from_screen(IDirectDrawSurfaceImpl* This, LPCRECT rc)
551 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
553 POINT offset;
554 HWND hDisplayWnd = get_display_window(This, &offset);
555 HDC hDisplayDC = GetDC(hDisplayWnd);
556 RECT drawrect;
558 drawrect.left = 0;
559 drawrect.right = This->surface_desc.dwWidth;
560 drawrect.top = 0;
561 drawrect.bottom = This->surface_desc.dwHeight;
562 if (rc)
563 IntersectRect(&drawrect,&drawrect,rc);
565 BitBlt(This->hDC,
566 drawrect.left, drawrect.top,
567 drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
568 hDisplayDC,
569 drawrect.left+offset.x, drawrect.top+offset.y,
570 SRCCOPY
572 ReleaseDC(hDisplayWnd, hDisplayDC);
576 static ICOM_VTABLE(IDirectDrawSurface7) User_IDirectDrawSurface7_VTable =
578 Main_DirectDrawSurface_QueryInterface,
579 Main_DirectDrawSurface_AddRef,
580 Main_DirectDrawSurface_Release,
581 Main_DirectDrawSurface_AddAttachedSurface,
582 Main_DirectDrawSurface_AddOverlayDirtyRect,
583 DIB_DirectDrawSurface_Blt,
584 Main_DirectDrawSurface_BltBatch,
585 DIB_DirectDrawSurface_BltFast,
586 Main_DirectDrawSurface_DeleteAttachedSurface,
587 Main_DirectDrawSurface_EnumAttachedSurfaces,
588 Main_DirectDrawSurface_EnumOverlayZOrders,
589 Main_DirectDrawSurface_Flip,
590 Main_DirectDrawSurface_GetAttachedSurface,
591 Main_DirectDrawSurface_GetBltStatus,
592 Main_DirectDrawSurface_GetCaps,
593 Main_DirectDrawSurface_GetClipper,
594 Main_DirectDrawSurface_GetColorKey,
595 Main_DirectDrawSurface_GetDC,
596 Main_DirectDrawSurface_GetFlipStatus,
597 Main_DirectDrawSurface_GetOverlayPosition,
598 Main_DirectDrawSurface_GetPalette,
599 Main_DirectDrawSurface_GetPixelFormat,
600 Main_DirectDrawSurface_GetSurfaceDesc,
601 Main_DirectDrawSurface_Initialize,
602 Main_DirectDrawSurface_IsLost,
603 Main_DirectDrawSurface_Lock,
604 Main_DirectDrawSurface_ReleaseDC,
605 DIB_DirectDrawSurface_Restore,
606 Main_DirectDrawSurface_SetClipper,
607 Main_DirectDrawSurface_SetColorKey,
608 Main_DirectDrawSurface_SetOverlayPosition,
609 Main_DirectDrawSurface_SetPalette,
610 Main_DirectDrawSurface_Unlock,
611 Main_DirectDrawSurface_UpdateOverlay,
612 Main_DirectDrawSurface_UpdateOverlayDisplay,
613 Main_DirectDrawSurface_UpdateOverlayZOrder,
614 Main_DirectDrawSurface_GetDDInterface,
615 Main_DirectDrawSurface_PageLock,
616 Main_DirectDrawSurface_PageUnlock,
617 DIB_DirectDrawSurface_SetSurfaceDesc,
618 Main_DirectDrawSurface_SetPrivateData,
619 Main_DirectDrawSurface_GetPrivateData,
620 Main_DirectDrawSurface_FreePrivateData,
621 Main_DirectDrawSurface_GetUniquenessValue,
622 Main_DirectDrawSurface_ChangeUniquenessValue,
623 Main_DirectDrawSurface_SetPriority,
624 Main_DirectDrawSurface_GetPriority,
625 Main_DirectDrawSurface_SetLOD,
626 Main_DirectDrawSurface_GetLOD