ddraw: Remove a redundant check from ddraw7_SetCooperativeLevel().
[wine] / dlls / ddraw / tests / overlay.c
1 /*
2  * Unit tests for DirectDraw overlay functions
3  *
4  * Copyright (C) 2008 Stefan Dösinger for CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20 #define COBJMACROS
21
22 #include <assert.h>
23 #include "wine/test.h"
24 #include "ddraw.h"
25 #include "unknwn.h"
26
27 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
28
29 static IDirectDraw7 *ddraw = NULL;
30 static IDirectDrawSurface7 *primary = NULL;
31
32 static IDirectDrawSurface7 *create_overlay(DWORD width, DWORD height, DWORD format) {
33     DDSURFACEDESC2 ddsd;
34     HRESULT hr;
35     IDirectDrawSurface7 *ret;
36
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;
49 }
50
51 static BOOL CreateDirectDraw(void)
52 {
53     HRESULT hr;
54     DDSURFACEDESC2 ddsd;
55     IDirectDrawSurface7 *overlay = NULL;
56     HMODULE hmod = GetModuleHandleA("ddraw.dll");
57
58     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
59     if (!pDirectDrawCreateEx) {
60         win_skip("DirectDrawCreateEx is not available\n");
61         return FALSE;
62     }
63
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;
69     }
70
71     hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
72     ok(hr == DD_OK, "SetCooperativeLevel returned: %x\n", hr );
73
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;
83     }
84
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;
91     }
92     IDirectDraw7_Release(overlay);
93
94     return TRUE;
95 }
96
97 static void rectangle_settings(void) {
98     IDirectDrawSurface7 *overlay = create_overlay(64, 64, MAKEFOURCC('U','Y','V','Y'));
99     HRESULT hr;
100     RECT rect = {0, 0, 64, 64};
101     LONG posx, posy;
102
103     /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is used. Show that this is wrong */
104     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
105     ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
106     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
107     ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
108     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
109     ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
110
111     /* Show that the overlay position is the (top, left) coordinate of the dest rectangle */
112     rect.top += 16;
113     rect.left += 32;
114     rect.bottom += 16;
115     rect.right += 32;
116     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
117     ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
118     posx = -1; posy = -1;
119     hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &posx, &posy);
120     ok(hr == DD_OK, "IDirectDrawSurface7_GetOverlayPosition failed with hr=0x%08x\n", hr);
121     ok(posx == rect.left && posy == rect.top, "Overlay position is (%d, %d), expected (%d, %d)\n",
122        posx, posy, rect.left, rect.top);
123
124     /* Passing a NULL dest rect sets the position to 0/0 . Visually it can be seen that the overlay overlays the whole primary(==screen)*/
125     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
126     ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
127     hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &posx, &posy);
128     ok(hr == DD_OK, "IDirectDrawSurface7_GetOverlayPosition failed with hr=0x%08x\n", hr);
129     ok(posx == 0 && posy == 0, "Overlay position is (%d, %d), expected (%d, %d)\n",
130        posx, posy, 0, 0);
131
132     /* The position cannot be retrieved when the overlay is not shown */
133     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
134     ok(hr == DD_OK, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
135     posx = -1; posy = -1;
136     hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &posx, &posy);
137     ok(hr == DDERR_OVERLAYNOTVISIBLE, "IDirectDrawSurface7_GetOverlayPosition failed with hr=0x%08x\n", hr);
138     ok(posx == 0 && posy == 0, "Overlay position is (%d, %d), expected (%d, %d)\n",
139        posx, posy, 0, 0);
140
141     IDirectDrawSurface7_Release(overlay);
142 }
143
144 static void offscreen_test(void) {
145     IDirectDrawSurface7 *overlay = create_overlay(64, 64, MAKEFOURCC('U','Y','V','Y')), *offscreen = NULL;
146     HRESULT hr;
147     DDSURFACEDESC2 ddsd;
148
149     /* Try to overlay a NULL surface */
150     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
151     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
152     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
153     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
154
155     /* Try to overlay an offscreen surface */
156     memset(&ddsd, 0, sizeof(ddsd));
157     ddsd.dwSize = sizeof(ddsd);
158     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
159     ddsd.dwWidth = 64;
160     ddsd.dwHeight = 64;
161     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
162     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
163     U4(ddsd).ddpfPixelFormat.dwFourCC = 0;
164     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
165     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
166     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07e0;
167     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
168     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
169     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
170     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed with hr=0x%08x\n", hr);
171
172     hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
173     ok(hr == DD_OK || broken(hr == E_NOTIMPL),
174        "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
175
176     /* Try to overlay the primary with a non-overlay surface */
177     hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
178     ok(hr == DDERR_NOTAOVERLAYSURFACE, "IDirectDrawSurface7_UpdateOverlay failed with hr=0x%08x\n", hr);
179
180     IDirectDrawSurface7_Release(offscreen);
181     IDirectDrawSurface7_Release(overlay);
182 }
183
184 static void yv12_test(void)
185 {
186     HRESULT hr;
187     DDSURFACEDESC2 desc;
188     IDirectDrawSurface7 *surface;
189
190     surface = create_overlay(256, 256, MAKEFOURCC('Y','V','1','2'));
191     if(!surface) {
192         skip("YV12 surfaces not available\n");
193         return;
194     }
195
196     memset(&desc, 0, sizeof(desc));
197     desc.dwSize = sizeof(desc);
198     hr = IDirectDrawSurface7_Lock(surface, NULL, &desc, 0, NULL);
199     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned 0x%08x, expected DD_OK\n", hr);
200
201     ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
202        "Unexpected desc.dwFlags 0x%08x\n", desc.dwFlags);
203     ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM) ||
204        desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC),
205        "Unexpected desc.ddsCaps.dwCaps 0x%08x\n", desc.ddsCaps.dwCaps);
206     ok(desc.dwWidth == 256 && desc.dwHeight == 256, "Expected size 64x64, got %ux%u\n",
207        desc.dwWidth, desc.dwHeight);
208     /* The overlay pitch seems to have 256 byte alignment */
209     ok(U1(desc).lPitch == 256, "Unexpected pitch %u, expected 256\n", U1(desc).lPitch);
210
211     hr = IDirectDrawSurface7_Unlock(surface, NULL);
212     ok(hr == DD_OK, "IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK\n", hr);
213
214     IDirectDrawSurface7_Release(surface);
215 }
216
217 START_TEST(overlay)
218 {
219     if(CreateDirectDraw() == FALSE) {
220         skip("Failed to initialize ddraw\n");
221         return;
222     }
223
224     rectangle_settings();
225     offscreen_test();
226     yv12_test();
227
228     if(primary) IDirectDrawSurface7_Release(primary);
229     if(ddraw) IDirectDraw7_Release(ddraw);
230 }