mshtml: Wine Gecko 2.34-beta2 release.
[wine/wine-gecko.git] / dlls / ddraw / tests / overlay.c
blob7e22ccaeb2b6559795cc513013add8616550cadc
1 /*
2 * Unit tests for DirectDraw overlay functions
4 * Copyright (C) 2008,2011 Stefan Dösinger for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include "wine/test.h"
23 #include "ddraw.h"
24 #include "unknwn.h"
26 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *driver_guid,
27 void **ddraw, REFIID interface_iid, IUnknown *outer);
29 static IDirectDraw7 *ddraw = NULL;
30 static IDirectDrawSurface7 *primary = NULL;
32 static IDirectDrawSurface7 *create_overlay(DWORD width, DWORD height, DWORD format) {
33 DDSURFACEDESC2 ddsd;
34 HRESULT hr;
35 IDirectDrawSurface7 *ret;
37 memset(&ddsd, 0, sizeof(ddsd));
38 ddsd.dwSize = sizeof(ddsd);
39 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
40 ddsd.dwWidth = width;
41 ddsd.dwHeight = height;
42 ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
43 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
44 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
45 U4(ddsd).ddpfPixelFormat.dwFourCC = format;
46 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &ret, NULL);
47 if(FAILED(hr)) return NULL;
48 else return ret;
51 static BOOL CreateDirectDraw(void)
53 HRESULT hr;
54 DDSURFACEDESC2 ddsd;
55 IDirectDrawSurface7 *overlay = NULL;
56 HMODULE hmod = GetModuleHandleA("ddraw.dll");
58 pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
59 if (!pDirectDrawCreateEx) {
60 win_skip("DirectDrawCreateEx is not available\n");
61 return FALSE;
64 hr = pDirectDrawCreateEx(NULL, (void**)&ddraw, &IID_IDirectDraw7, NULL);
65 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", hr);
66 if (!ddraw) {
67 trace("DirectDrawCreateEx() failed with an error %x\n", hr);
68 return FALSE;
71 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
72 ok(hr == DD_OK, "SetCooperativeLevel returned: %x\n", hr );
74 memset(&ddsd, 0, sizeof(ddsd));
75 ddsd.dwSize = sizeof(ddsd);
76 ddsd.dwFlags = DDSD_CAPS;
77 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
78 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
79 if (FAILED(hr)) {
80 IDirectDraw7_Release(ddraw);
81 trace("IDirectDraw7_CreateSurface() failed with an error %x\n", hr);
82 return FALSE;
85 overlay = create_overlay(64, 64, MAKEFOURCC('U','Y','V','Y'));
86 if (!overlay) {
87 IDirectDrawSurface7_Release(primary);
88 IDirectDraw7_Release(ddraw);
89 skip("Failed to create an overlay - assuming not supported\n");
90 return FALSE;
92 IDirectDraw7_Release(overlay);
94 return TRUE;
97 static void rectangle_settings(void) {
98 IDirectDrawSurface7 *overlay = create_overlay(64, 64, MAKEFOURCC('U','Y','V','Y'));
99 HRESULT hr, hr2;
100 RECT rect = {0, 0, 64, 64};
101 LONG posx, posy;
103 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is used. This is not true
104 * in Windows Vista and earlier, but changed in Win7 */
105 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
106 ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
107 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
108 ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
109 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
110 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
112 /* Show that the overlay position is the (top, left) coordinate of the dest rectangle */
113 rect.top += 16;
114 rect.left += 32;
115 rect.bottom += 16;
116 rect.right += 32;
117 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
118 ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
119 posx = -1; posy = -1;
120 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &posx, &posy);
121 ok(hr == DD_OK, "IDirectDrawSurface7_GetOverlayPosition failed with hr=0x%08x\n", hr);
122 ok(posx == rect.left && posy == rect.top, "Overlay position is (%d, %d), expected (%d, %d)\n",
123 posx, posy, rect.left, rect.top);
125 /* Passing a NULL dest rect sets the position to 0/0 . Visually it can be seen that the overlay overlays the whole primary(==screen)*/
126 hr2 = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
127 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS
128 || hr2 == DDERR_OUTOFCAPS, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr2);
129 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &posx, &posy);
130 ok(hr == DD_OK, "IDirectDrawSurface7_GetOverlayPosition failed with hr=0x%08x\n", hr);
131 if (SUCCEEDED(hr2))
133 ok(posx == 0 && posy == 0, "Overlay position is (%d, %d), expected (%d, %d)\n",
134 posx, posy, 0, 0);
136 else
138 /* Otherwise the position remains untouched */
139 ok(posx == 32 && posy == 16, "Overlay position is (%d, %d), expected (%d, %d)\n",
140 posx, posy, 32, 16);
142 /* The position cannot be retrieved when the overlay is not shown */
143 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
144 ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
145 posx = -1; posy = -1;
146 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &posx, &posy);
147 ok(hr == DDERR_OVERLAYNOTVISIBLE, "IDirectDrawSurface7_GetOverlayPosition failed with hr=0x%08x\n", hr);
148 ok(posx == 0 && posy == 0, "Overlay position is (%d, %d), expected (%d, %d)\n",
149 posx, posy, 0, 0);
151 IDirectDrawSurface7_Release(overlay);
154 static void offscreen_test(void) {
155 IDirectDrawSurface7 *overlay = create_overlay(64, 64, MAKEFOURCC('U','Y','V','Y')), *offscreen = NULL;
156 HRESULT hr;
157 DDSURFACEDESC2 ddsd;
159 /* Try to overlay a NULL surface */
160 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
161 ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
162 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
163 ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
165 /* Try to overlay an offscreen surface */
166 memset(&ddsd, 0, sizeof(ddsd));
167 ddsd.dwSize = sizeof(ddsd);
168 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
169 ddsd.dwWidth = 64;
170 ddsd.dwHeight = 64;
171 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
172 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
173 U4(ddsd).ddpfPixelFormat.dwFourCC = 0;
174 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
175 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
176 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07e0;
177 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
178 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
179 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
180 ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed with hr=0x%08x\n", hr);
182 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
183 ok(hr == DD_OK || broken(hr == E_NOTIMPL),
184 "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
186 /* Try to overlay the primary with a non-overlay surface */
187 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
188 ok(hr == DDERR_NOTAOVERLAYSURFACE, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
190 IDirectDrawSurface7_Release(offscreen);
191 IDirectDrawSurface7_Release(overlay);
194 static void yv12_test(void)
196 HRESULT hr;
197 DDSURFACEDESC2 desc;
198 IDirectDrawSurface7 *surface, *dst;
199 char *base;
200 RECT rect = {13, 17, 14, 18};
201 unsigned int offset, y;
203 surface = create_overlay(256, 256, MAKEFOURCC('Y','V','1','2'));
204 if(!surface) {
205 skip("YV12 surfaces not available\n");
206 return;
209 memset(&desc, 0, sizeof(desc));
210 desc.dwSize = sizeof(desc);
211 hr = IDirectDrawSurface7_Lock(surface, NULL, &desc, 0, NULL);
212 ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned 0x%08x, expected DD_OK\n", hr);
214 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
215 "Unexpected desc.dwFlags 0x%08x\n", desc.dwFlags);
216 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM) ||
217 desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC),
218 "Unexpected desc.ddsCaps.dwCaps 0x%08x\n", desc.ddsCaps.dwCaps);
219 ok(desc.dwWidth == 256 && desc.dwHeight == 256, "Expected size 256x256, got %ux%u\n",
220 desc.dwWidth, desc.dwHeight);
221 /* The overlay pitch seems to have 256 byte alignment */
222 ok((U1(desc).lPitch & 0xff) == 0, "Expected 256 byte aligned pitch, got %u\n", U1(desc).lPitch);
224 /* Fill the surface with some data for the blit test */
225 base = desc.lpSurface;
226 /* Luminance */
227 for (y = 0; y < desc.dwHeight; y++)
229 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
231 /* V */
232 for (; y < desc.dwHeight + desc.dwHeight / 4; y++)
234 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
236 /* U */
237 for (; y < desc.dwHeight + desc.dwHeight / 2; y++)
239 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
242 hr = IDirectDrawSurface7_Unlock(surface, NULL);
243 ok(hr == DD_OK, "IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK\n", hr);
245 /* YV12 uses 2x2 blocks with 6 bytes per block(4*Y, 1*U, 1*V). Unlike other block-based formats like DXT
246 * the entire Y channel is stored in one big chunk of memory, followed by the chroma channels. So
247 * partial locks do not really make sense. Show that they are allowed nevertheless and the offset points
248 * into the luminance data */
249 hr = IDirectDrawSurface7_Lock(surface, &rect, &desc, 0, NULL);
250 ok(hr == DD_OK, "Partial lock of a YV12 surface returned 0x%08x, expected DD_OK\n", hr);
251 offset = ((const char *) desc.lpSurface - base);
252 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Expected %u byte offset from partial lock, got %u\n",
253 rect.top * U1(desc).lPitch + rect.left, offset);
254 hr = IDirectDrawSurface7_Unlock(surface, NULL);
255 ok(hr == DD_OK, "IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK\n", hr);
257 dst = create_overlay(256, 256, MAKEFOURCC('Y','V','1','2'));
258 if (!dst)
260 /* Windows XP with a Radeon X1600 GPU refuses to create a second overlay surface,
261 * DDERR_NOOVERLAYHW, making the blit tests moot */
262 skip("Could not create a second YV12 surface, skipping blit test\n");
263 goto cleanup;
266 hr = IDirectDrawSurface7_Blt(dst, NULL, surface, NULL, 0, NULL);
267 /* VMware rejects YV12 blits. This behavior has not been seen on real hardware yet, so mark it broken */
268 ok(hr == DD_OK || broken(hr == E_NOTIMPL),
269 "IDirectDrawSurface7_Blt returned 0x%08x, expected DD_OK\n", hr);
271 if (SUCCEEDED(hr))
273 memset(&desc, 0, sizeof(desc));
274 desc.dwSize = sizeof(desc);
275 hr = IDirectDrawSurface7_Lock(dst, NULL, &desc, 0, NULL);
276 ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned 0x%08x, expected DD_OK\n", hr);
278 base = desc.lpSurface;
279 ok(base[0] == 0x10, "Y data is 0x%02x, expected 0x10\n", base[0]);
280 base += desc.dwHeight * U1(desc).lPitch;
281 todo_wine ok(base[0] == 0x20, "V data is 0x%02x, expected 0x20\n", base[0]);
282 base += desc.dwHeight / 4 * U1(desc).lPitch;
283 todo_wine ok(base[0] == 0x30, "U data is 0x%02x, expected 0x30\n", base[0]);
285 hr = IDirectDrawSurface7_Unlock(dst, NULL);
286 ok(hr == DD_OK, "IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK\n", hr);
289 IDirectDrawSurface7_Release(dst);
290 cleanup:
291 IDirectDrawSurface7_Release(surface);
294 START_TEST(overlay)
296 if(CreateDirectDraw() == FALSE) {
297 skip("Failed to initialize ddraw\n");
298 return;
301 rectangle_settings();
302 offscreen_test();
303 yv12_test();
305 if(primary) IDirectDrawSurface7_Release(primary);
306 if(ddraw) IDirectDraw7_Release(ddraw);