tests: Make some variables static.
[wine] / dlls / ddraw / tests / visual.c
1 /*
2  * Copyright (C) 2007 Stefan Dösinger(for CodeWeavers)
3  * Copyright (C) 2008 Alexander Dorofeyev
4  *
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.
9  *
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.
14  *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 /* See comment in dlls/d3d9/tests/visual.c for general guidelines */
21
22 #include <assert.h>
23 #include "wine/test.h"
24 #include "ddraw.h"
25 #include "d3d.h"
26
27 static HWND window;
28 static IDirectDraw7        *DirectDraw;
29 static IDirectDrawSurface7 *Surface;
30 static IDirectDrawSurface7 *depth_buffer;
31 static IDirect3D7          *Direct3D;
32 static IDirect3DDevice7    *Direct3DDevice;
33
34 static IDirectDraw *DirectDraw1;
35 static IDirectDrawSurface *Surface1;
36 static IDirect3D *Direct3D1;
37 static IDirect3DDevice *Direct3DDevice1;
38 static IDirect3DExecuteBuffer *ExecuteBuffer;
39 static IDirect3DViewport *Viewport;
40
41 static BOOL refdevice = FALSE;
42
43 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
44
45 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
46 {
47     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
48     c1 >>= 8; c2 >>= 8;
49     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
50     c1 >>= 8; c2 >>= 8;
51     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
52     c1 >>= 8; c2 >>= 8;
53     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
54     return TRUE;
55 }
56
57 static BOOL createObjects(void)
58 {
59     HRESULT hr;
60     HMODULE hmod = GetModuleHandleA("ddraw.dll");
61     WNDCLASS wc = {0};
62     DDSURFACEDESC2 ddsd;
63
64
65     if(!hmod) return FALSE;
66     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
67     if(!pDirectDrawCreateEx) return FALSE;
68
69     hr = pDirectDrawCreateEx(NULL, (void **) &DirectDraw, &IID_IDirectDraw7, NULL);
70     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", hr);
71     if(!DirectDraw) goto err;
72
73     wc.lpfnWndProc = DefWindowProc;
74     wc.lpszClassName = "d3d7_test_wc";
75     RegisterClass(&wc);
76     window = CreateWindow("d3d7_test_wc", "d3d7_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
77
78     hr = IDirectDraw7_SetCooperativeLevel(DirectDraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
79     ok(hr == DD_OK, "IDirectDraw7_SetCooperativeLevel failed with %08x\n", hr);
80     if(FAILED(hr)) goto err;
81     hr = IDirectDraw7_SetDisplayMode(DirectDraw, 640, 480, 32, 0, 0);
82     if(FAILED(hr)) {
83         /* 24 bit is fine too */
84         hr = IDirectDraw7_SetDisplayMode(DirectDraw, 640, 480, 24, 0, 0);
85
86     }
87     ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "IDirectDraw7_SetDisplayMode failed with %08x\n", hr);
88     if(FAILED(hr)) {
89         /* use trace, the caller calls skip() */
90         trace("SetDisplayMode failed\n");
91         goto err;
92     }
93
94     hr = IDirectDraw7_QueryInterface(DirectDraw, &IID_IDirect3D7, (void**) &Direct3D);
95     if (hr == E_NOINTERFACE) goto err;
96     ok(hr==DD_OK, "QueryInterface returned: %08x\n", hr);
97
98     /* DirectDraw Flipping behavior doesn't seem that well-defined. The reference rasterizer behaves differently
99      * than hardware implementations. Request single buffering, that seems to work everywhere
100      */
101     memset(&ddsd, 0, sizeof(ddsd));
102     ddsd.dwSize = sizeof(ddsd);
103     ddsd.dwFlags = DDSD_CAPS;
104     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
105     ddsd.dwBackBufferCount = 1;
106     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &Surface, NULL);
107     if(FAILED(hr)) goto err;
108
109     memset(&ddsd, 0, sizeof(ddsd));
110     ddsd.dwSize = sizeof(ddsd);
111     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
112     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
113     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
114     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
115     U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 32;
116     U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x00ffffff;
117     ddsd.dwWidth = 640;
118     ddsd.dwHeight = 480;
119     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &depth_buffer, NULL);
120     ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
121     if (FAILED(hr)) goto err;
122
123     hr = IDirectDrawSurface_AddAttachedSurface(Surface, depth_buffer);
124     ok(SUCCEEDED(hr), "AddAttachedSurface failed, hr %#x.\n", hr);
125     if (FAILED(hr)) goto err;
126
127     hr = IDirect3D7_CreateDevice(Direct3D, &IID_IDirect3DTnLHalDevice, Surface, &Direct3DDevice);
128     if(FAILED(hr))
129     {
130         trace("Creating a TnLHal Device failed, trying HAL\n");
131         hr = IDirect3D7_CreateDevice(Direct3D, &IID_IDirect3DHALDevice, Surface, &Direct3DDevice);
132         if(FAILED(hr))
133         {
134             trace("Creating a HAL device failed, trying Ref\n");
135             hr = IDirect3D7_CreateDevice(Direct3D, &IID_IDirect3DRefDevice, Surface, &Direct3DDevice);
136             if (SUCCEEDED(hr))
137                 refdevice = TRUE;
138         }
139     }
140     if(!Direct3DDevice) goto err;
141     return TRUE;
142
143     err:
144     if(DirectDraw) IDirectDraw7_Release(DirectDraw);
145     if (depth_buffer) IDirectDrawSurface7_Release(depth_buffer);
146     if(Surface) IDirectDrawSurface7_Release(Surface);
147     if(Direct3D) IDirect3D7_Release(Direct3D);
148     if(Direct3DDevice) IDirect3DDevice7_Release(Direct3DDevice);
149     if(window) DestroyWindow(window);
150     return FALSE;
151 }
152
153 static void releaseObjects(void)
154 {
155     IDirect3DDevice7_Release(Direct3DDevice);
156     IDirect3D7_Release(Direct3D);
157     IDirectDrawSurface7_Release(depth_buffer);
158     IDirectDrawSurface7_Release(Surface);
159     IDirectDraw7_Release(DirectDraw);
160     DestroyWindow(window);
161 }
162
163 static DWORD getPixelColor(IDirect3DDevice7 *device, UINT x, UINT y)
164 {
165     DWORD ret;
166     HRESULT hr;
167     DDSURFACEDESC2 ddsd;
168     RECT rectToLock = {x, y, x+1, y+1};
169     IDirectDrawSurface7 *surf = NULL;
170
171     /* Some implementations seem to dislike direct locking on the front buffer. Thus copy the front buffer
172      * to an offscreen surface and lock it instead of the front buffer
173      */
174     memset(&ddsd, 0, sizeof(ddsd));
175     ddsd.dwSize = sizeof(ddsd);
176     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
177     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
178     ddsd.dwWidth = 640;
179     ddsd.dwHeight = 480;
180     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
181     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &surf, NULL);
182     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed with %08x\n", hr);
183     if(!surf)
184     {
185         trace("cannot create helper surface\n");
186         return 0xdeadbeef;
187     }
188
189     memset(&ddsd, 0, sizeof(ddsd));
190     ddsd.dwSize = sizeof(ddsd);
191     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
192
193     hr = IDirectDrawSurface_BltFast(surf, 0, 0, Surface, NULL, 0);
194     ok(hr == DD_OK, "IDirectDrawSurface7_BltFast returned %08x\n", hr);
195     if(FAILED(hr))
196     {
197         trace("Cannot blit\n");
198         ret = 0xdeadbee;
199         goto out;
200     }
201
202     hr = IDirectDrawSurface7_Lock(surf, &rectToLock, &ddsd, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
203     if(FAILED(hr))
204     {
205         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
206         ret = 0xdeadbeec;
207         goto out;
208     }
209
210     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
211      * really important for these tests
212      */
213     ret = ((DWORD *) ddsd.lpSurface)[0] & 0x00ffffff;
214     hr = IDirectDrawSurface7_Unlock(surf, NULL);
215     if(FAILED(hr))
216     {
217         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
218     }
219
220 out:
221     IDirectDrawSurface7_Release(surf);
222     return ret;
223 }
224
225 /*
226  * Helper function to get and set the viewport - needed on geforce 8800 on XP - driver bug?
227  * This is needed after IDirect3DDevice7_SetRenderTarget in combination with offscreen to backbuffer rendering.
228  */
229 static void set_the_same_viewport_again(IDirect3DDevice7 *device)
230 {
231     D3DVIEWPORT7 vp = {0};
232     HRESULT hr;
233     hr = IDirect3DDevice7_GetViewport(device,&vp);
234     ok(hr == D3D_OK && vp.dwWidth == 640 && vp.dwHeight == 480, "IDirect3DDevice7_SetViewport returned %08x\n", hr);
235     hr = IDirect3DDevice7_SetViewport(device, &vp);
236     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport returned %08x\n", hr);
237     return;
238 }
239
240 struct vertex
241 {
242     float x, y, z;
243     DWORD diffuse;
244 };
245
246 struct tvertex
247 {
248     float x, y, z, w;
249     DWORD diffuse;
250 };
251
252 struct nvertex
253 {
254     float x, y, z;
255     float nx, ny, nz;
256     DWORD diffuse;
257 };
258
259 static void lighting_test(IDirect3DDevice7 *device)
260 {
261     HRESULT hr;
262     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
263     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
264     DWORD color;
265
266     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
267                       0.0f, 1.0f, 0.0f, 0.0f,
268                       0.0f, 0.0f, 1.0f, 0.0f,
269                       0.0f, 0.0f, 0.0f, 1.0f };
270
271     struct vertex unlitquad[] =
272     {
273         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
274         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
275         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
276         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
277     };
278     struct vertex litquad[] =
279     {
280         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
281         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
282         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
283         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
284     };
285     struct nvertex unlitnquad[] =
286     {
287         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
288         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
289         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
290         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
291     };
292     struct nvertex litnquad[] =
293     {
294         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
295         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
296         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
297         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
298     };
299     WORD Indices[] = {0, 1, 2, 2, 3, 0};
300
301     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
302     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
303
304     /* Setup some states that may cause issues */
305     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, (D3DMATRIX *) mat);
306     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
307     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, (D3DMATRIX *)mat);
308     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
309     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, (D3DMATRIX *) mat);
310     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
311     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
312     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
313     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
314     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
315     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
316     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
317     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
318     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
319     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
320     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
321     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
322     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
323     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
324     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed with %08x\n", hr);
325
326     hr = IDirect3DDevice7_BeginScene(device);
327     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
328     if(hr == D3D_OK)
329     {
330         /* No lights are defined... That means, lit vertices should be entirely black */
331         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
332         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
333         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4 /* NumVerts */,
334                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
335         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
336
337         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
338         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
339         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4 /* NumVerts */,
340                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
341         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
342
343         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
344         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
345         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4 /* NumVerts */,
346                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
347         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
348
349         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
350         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
351         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4 /* NumVerts */,
352                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
353         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
354
355         IDirect3DDevice7_EndScene(device);
356         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
357     }
358
359     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
360     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
361     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
362     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
363     color = getPixelColor(device, 480, 360); /* lower left quad - unlit width normals */
364     ok(color == 0x000000ff, "Unlit quad width normals has color %08x\n", color);
365     color = getPixelColor(device, 480, 120); /* upper left quad - lit width normals */
366     ok(color == 0x00000000, "Lit quad width normals has color %08x\n", color);
367
368     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
369     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
370 }
371
372 static void clear_test(IDirect3DDevice7 *device)
373 {
374     /* Tests the correctness of clearing parameters */
375     HRESULT hr;
376     D3DRECT rect[2];
377     D3DRECT rect_negneg;
378     DWORD color;
379
380     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
381     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
382
383     /* Positive x, negative y */
384     U1(rect[0]).x1 = 0;
385     U2(rect[0]).y1 = 480;
386     U3(rect[0]).x2 = 320;
387     U4(rect[0]).y2 = 240;
388
389     /* Positive x, positive y */
390     U1(rect[1]).x1 = 0;
391     U2(rect[1]).y1 = 0;
392     U3(rect[1]).x2 = 320;
393     U4(rect[1]).y2 = 240;
394     /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
395      * is ignored, the positive is still cleared afterwards
396      */
397     hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
398     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
399
400     /* negative x, negative y */
401     U1(rect_negneg).x1 = 640;
402     U2(rect_negneg).y1 = 240;
403     U3(rect_negneg).x2 = 320;
404     U4(rect_negneg).y2 = 0;
405     hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
406     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
407
408     color = getPixelColor(device, 160, 360); /* lower left quad */
409     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
410     color = getPixelColor(device, 160, 120); /* upper left quad */
411     ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
412     color = getPixelColor(device, 480, 360); /* lower right quad  */
413     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
414     color = getPixelColor(device, 480, 120); /* upper right quad */
415     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
416 }
417
418 struct sVertex {
419     float x, y, z;
420     DWORD diffuse;
421     DWORD specular;
422 };
423
424 struct sVertexT {
425     float x, y, z, rhw;
426     DWORD diffuse;
427     DWORD specular;
428 };
429
430 static void fog_test(IDirect3DDevice7 *device)
431 {
432     HRESULT hr;
433     DWORD color;
434     float start = 0.0, end = 1.0;
435     D3DDEVICEDESC7 caps;
436
437     /* Gets full z based fog with linear fog, no fog with specular color */
438     struct sVertex unstransformed_1[] = {
439         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
440         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
441         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
442         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
443     };
444     /* Ok, I am too lazy to deal with transform matrices */
445     struct sVertex unstransformed_2[] = {
446         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
447         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
448         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
449         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
450     };
451     /* Untransformed ones. Give them a different diffuse color to make the test look
452      * nicer. It also makes making sure that they are drawn correctly easier.
453      */
454     struct sVertexT transformed_1[] = {
455         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
456         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
457         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
458         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
459     };
460     struct sVertexT transformed_2[] = {
461         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
462         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
463         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
464         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
465     };
466     WORD Indices[] = {0, 1, 2, 2, 3, 0};
467
468     memset(&caps, 0, sizeof(caps));
469     hr = IDirect3DDevice7_GetCaps(device, &caps);
470     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
471     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
472     ok(hr == D3D_OK, "IDirect3DDevice7_Clear returned %08x\n", hr);
473
474     /* Setup initial states: No lighting, fog on, fog color */
475     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
476     ok(hr == D3D_OK, "Turning off lighting returned %08x\n", hr);
477     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
478     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
479     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xFF00FF00 /* A nice green */);
480     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
481
482     /* First test: Both table fog and vertex fog off */
483     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
484     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
485     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE);
486     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
487
488     /* Start = 0, end = 1. Should be default, but set them */
489     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, *((DWORD *) &start));
490     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
491     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, *((DWORD *) &end));
492     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
493
494     if(IDirect3DDevice7_BeginScene(device) == D3D_OK)
495     {
496         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
497         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
498                                                    unstransformed_1, 4, Indices, 6, 0);
499         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
500
501         /* That makes it use the Z value */
502         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
503         ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
504         /* Untransformed, vertex fog != none (or table fog != none):
505          * Use the Z value as input into the equation
506          */
507         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
508                                                    unstransformed_2, 4, Indices, 6, 0);
509         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
510
511         /* transformed verts */
512         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
513         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
514         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
515                                                    transformed_1, 4, Indices, 6, 0);
516         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
517
518         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
519         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
520         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
521          * equation
522          */
523         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
524                                                    transformed_2, 4, Indices, 6, 0);
525         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
526
527         hr = IDirect3DDevice7_EndScene(device);
528         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
529     }
530     else
531     {
532         ok(FALSE, "BeginScene failed\n");
533     }
534
535     color = getPixelColor(device, 160, 360);
536     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
537     color = getPixelColor(device, 160, 120);
538     ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
539     color = getPixelColor(device, 480, 120);
540     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
541     if(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE)
542     {
543         color = getPixelColor(device, 480, 360);
544         ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
545     }
546     else
547     {
548         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
549          * The settings above result in no fogging with vertex fog
550          */
551         color = getPixelColor(device, 480, 120);
552         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
553         trace("Info: Table fog not supported by this device\n");
554     }
555
556     /* Turn off the fog master switch to avoid confusing other tests */
557     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
558     ok(hr == D3D_OK, "Turning off fog calculations returned %08x\n", hr);
559 }
560
561 static void blt_test(IDirect3DDevice7 *device)
562 {
563     IDirectDrawSurface7 *backbuffer = NULL, *offscreen = NULL;
564     DDSURFACEDESC2 ddsd;
565     HRESULT hr;
566
567     memset(&ddsd, 0, sizeof(ddsd));
568     ddsd.dwSize = sizeof(ddsd);
569     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
570     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
571     ddsd.dwWidth = 640;
572     ddsd.dwHeight = 480;
573     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
574     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &offscreen, NULL);
575     ok(hr == D3D_OK, "Creating the offscreen render target failed, hr = %08x\n", hr);
576
577     /* Offscreen blits with the same source as destination */
578     if(SUCCEEDED(hr))
579     {
580         RECT src_rect, dst_rect;
581
582         /* Blit the whole surface to itself */
583         hr = IDirectDrawSurface_Blt(offscreen, NULL, offscreen, NULL, 0, NULL);
584         ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
585
586         /* Overlapped blit */
587         dst_rect.left = 0; dst_rect.right = 480;
588         dst_rect.top = 0; dst_rect.bottom = 480;
589         src_rect.left = 160; src_rect.right = 640;
590         src_rect.top = 0; src_rect.bottom = 480;
591         hr = IDirectDrawSurface_Blt(offscreen, &dst_rect, offscreen, &src_rect, 0, NULL);
592         ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
593
594         /* Overlapped blit, flip-y through source rectangle (not allowed) */
595         dst_rect.left = 0; dst_rect.right = 480;
596         dst_rect.top = 0; dst_rect.bottom = 480;
597         src_rect.left = 160; src_rect.right = 640;
598         src_rect.top = 480; src_rect.bottom = 0;
599         hr = IDirectDrawSurface_Blt(offscreen, &dst_rect, offscreen, &src_rect, 0, NULL);
600         ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface7_Blt returned %08x\n", hr);
601
602         /* Overlapped blit, with shrinking in x */
603         dst_rect.left = 0; dst_rect.right = 480;
604         dst_rect.top = 0; dst_rect.bottom = 480;
605         src_rect.left = 160; src_rect.right = 480;
606         src_rect.top = 0; src_rect.bottom = 480;
607         hr = IDirectDrawSurface_Blt(offscreen, &dst_rect, offscreen, &src_rect, 0, NULL);
608         ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
609     }
610
611     hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
612     ok(hr == D3D_OK, "Unable to obtain a surface pointer to the backbuffer, hr = %08x\n", hr);
613
614     /* backbuffer ==> texture blits */
615     if(SUCCEEDED(hr) && offscreen)
616     {
617         RECT src_rect, dst_rect;
618
619         /* backbuffer ==> texture, src_rect=NULL, dst_rect=NULL, no scaling */
620         hr = IDirectDrawSurface_Blt(offscreen, NULL, backbuffer, NULL, 0, NULL);
621         ok(hr == DD_OK, "fullscreen Blt from backbuffer => texture failed with hr = %08x\n", hr);
622
623         /* backbuffer ==> texture, full surface blits, no scaling */
624         dst_rect.left = 0; dst_rect.right = 640;
625         dst_rect.top = 0; dst_rect.bottom = 480;
626         src_rect.left = 0; src_rect.right = 640;
627         src_rect.top = 0; src_rect.bottom = 480;
628         hr = IDirectDrawSurface_Blt(offscreen, &dst_rect, backbuffer, &src_rect, 0, NULL);
629         ok(hr == DD_OK, "fullscreen Blt from backbuffer => texture failed with hr = %08x\n", hr);
630
631         /* backbuffer ==> texture, flip in y-direction through source rectangle, no scaling (allowed) */
632         dst_rect.left = 0; dst_rect.right = 640;
633         dst_rect.top = 480; dst_rect.top = 0;
634         src_rect.left = 0; src_rect.right = 640;
635         src_rect.top = 0; src_rect.bottom = 480;
636         hr = IDirectDrawSurface_Blt(offscreen, &dst_rect, backbuffer, &src_rect, 0, NULL);
637         ok(hr == DD_OK, "backbuffer => texture flip-y src_rect failed with hr = %08x\n", hr);
638
639         /* backbuffer ==> texture, flip in x-direction through source rectangle, no scaling (not allowed) */
640         dst_rect.left = 640; dst_rect.right = 0;
641         dst_rect.top = 0; dst_rect.top = 480;
642         src_rect.left = 0; src_rect.right = 640;
643         src_rect.top = 0; src_rect.bottom = 480;
644         hr = IDirectDrawSurface_Blt(offscreen, &dst_rect, backbuffer, &src_rect, 0, NULL);
645         ok(hr == DDERR_INVALIDRECT, "backbuffer => texture flip-x src_rect failed with hr = %08x\n", hr);
646
647         /* backbuffer ==> texture, flip in y-direction through destination rectangle (not allowed) */
648         dst_rect.left = 0; dst_rect.right = 640;
649         dst_rect.top = 0; dst_rect.top = 480;
650         src_rect.left = 0; src_rect.right = 640;
651         src_rect.top = 480; src_rect.bottom = 0;
652         hr = IDirectDrawSurface_Blt(offscreen, &dst_rect, backbuffer, &src_rect, 0, NULL);
653         ok(hr == DDERR_INVALIDRECT, "backbuffer => texture flip-y dst_rect failed with hr = %08x\n", hr);
654
655         /* backbuffer ==> texture, flip in x-direction through destination rectangle, no scaling (not allowed) */
656         dst_rect.left = 0; dst_rect.right = 640;
657         dst_rect.top = 0; dst_rect.top = 480;
658         src_rect.left = 640; src_rect.right = 0;
659         src_rect.top = 0; src_rect.bottom = 480;
660         hr = IDirectDrawSurface_Blt(offscreen, &dst_rect, backbuffer, &src_rect, 0, NULL);
661         ok(hr == DDERR_INVALIDRECT, "backbuffer => texture flip-x dst_rect failed with hr = %08x\n", hr);
662     }
663
664     if(offscreen) IDirectDrawSurface7_Release(offscreen);
665     if(backbuffer) IDirectDrawSurface7_Release(backbuffer);
666 }
667
668 static void offscreen_test(IDirect3DDevice7 *device)
669 {
670     HRESULT hr;
671     IDirectDrawSurface7 *backbuffer = NULL, *offscreen = NULL;
672     DWORD color;
673     DDSURFACEDESC2 ddsd;
674
675     static const float quad[][5] = {
676         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
677         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
678         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
679         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
680     };
681
682     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
683     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
684
685     memset(&ddsd, 0, sizeof(ddsd));
686     ddsd.dwSize = sizeof(ddsd);
687     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
688     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
689     ddsd.dwWidth = 128;
690     ddsd.dwHeight = 128;
691     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
692     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &offscreen, NULL);
693     ok(hr == D3D_OK, "Creating the offscreen render target failed, hr = %08x\n", hr);
694     if(!offscreen) {
695         goto out;
696     }
697
698     hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
699     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
700     if(!backbuffer) {
701         goto out;
702     }
703
704     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
705     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
706     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
707     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
708     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DFILTER_NEAREST);
709     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
710     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DFILTER_NEAREST);
711     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
712     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
713     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned hr = %08x\n", hr);
714
715     if (refdevice) {
716         win_skip("Tests would crash on W2K with a refdevice\n");
717         goto out;
718     }
719
720     if(IDirect3DDevice7_BeginScene(device) == D3D_OK) {
721         hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
722         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
723         hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
724         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
725
726         /* Draw without textures - Should result in a white quad */
727         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
728         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
729
730         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
731         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
732         set_the_same_viewport_again(device);
733
734         hr = IDirect3DDevice7_SetTexture(device, 0, offscreen);
735         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
736
737         /* This time with the texture */
738         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
739         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
740
741         IDirect3DDevice7_EndScene(device);
742     }
743
744     /* Center quad - should be white */
745     color = getPixelColor(device, 320, 240);
746     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
747     /* Some quad in the cleared part of the texture */
748     color = getPixelColor(device, 170, 240);
749     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
750     /* Part of the originally cleared back buffer */
751     color = getPixelColor(device, 10, 10);
752     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
753     if(0) {
754         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
755          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
756          * the offscreen rendering mode this test would succeed or fail
757          */
758         color = getPixelColor(device, 10, 470);
759         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
760     }
761
762 out:
763     hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
764     ok(SUCCEEDED(hr), "IDirect3DDevice7_SetTexture returned %#x.\n", hr);
765
766     /* restore things */
767     if(backbuffer) {
768         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
769         ok(SUCCEEDED(hr), "IDirect3DDevice7_SetRenderTarget returned %#x.\n", hr);
770         IDirectDrawSurface7_Release(backbuffer);
771     }
772     if(offscreen) {
773         IDirectDrawSurface7_Release(offscreen);
774     }
775 }
776
777 static void alpha_test(IDirect3DDevice7 *device)
778 {
779     HRESULT hr;
780     IDirectDrawSurface7 *backbuffer = NULL, *offscreen = NULL;
781     DWORD color, red, green, blue;
782     DDSURFACEDESC2 ddsd;
783
784     struct vertex quad1[] =
785     {
786         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
787         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
788         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
789         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
790     };
791     struct vertex quad2[] =
792     {
793         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
794         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
795         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
796         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
797     };
798     static const float composite_quad[][5] = {
799         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
800         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
801         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
802         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
803     };
804
805     /* Clear the render target with alpha = 0.5 */
806     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
807     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
808
809     memset(&ddsd, 0, sizeof(ddsd));
810     ddsd.dwSize = sizeof(ddsd);
811     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
812     ddsd.dwWidth = 128;
813     ddsd.dwHeight = 128;
814     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
815     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
816     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount      = 32;
817     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
818     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
819     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask         = 0x000000ff;
820     U5(U4(ddsd).ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
821     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &offscreen, NULL);
822     ok(hr == D3D_OK, "Creating the offscreen render target failed, hr = %08x\n", hr);
823     if(!offscreen) {
824         goto out;
825     }
826     hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
827     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
828     if(!backbuffer) {
829         goto out;
830     }
831
832     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
833     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
834     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
835     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
836     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DFILTER_NEAREST);
837     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
838     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DFILTER_NEAREST);
839     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
840
841     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
842     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
843
844     if (refdevice) {
845         win_skip("Tests would crash on W2K with a refdevice\n");
846         goto out;
847     }
848
849     if(IDirect3DDevice7_BeginScene(device) == D3D_OK) {
850
851         /* Draw two quads, one with src alpha blending, one with dest alpha blending. The
852          * SRCALPHA / INVSRCALPHA blend doesn't give any surprises. Colors are blended based on
853          * the input alpha
854          *
855          * The DESTALPHA / INVDESTALPHA do not "work" on the regular buffer because there is no alpha.
856          * They give essentially ZERO and ONE blend factors
857          */
858         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
859         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
860         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
861         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
862         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad1, 4, 0);
863         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
864
865         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTALPHA);
866         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
867         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVDESTALPHA);
868         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
869         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad2, 4, 0);
870         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
871
872         /* Switch to the offscreen buffer, and redo the testing. SRCALPHA and DESTALPHA. The offscreen buffer
873          * has a alpha channel on its own. Clear the offscreen buffer with alpha = 0.5 again, then draw the
874          * quads again. The SRCALPHA/INVSRCALPHA doesn't give any surprises, but the DESTALPHA/INVDESTALPHA
875          * blending works as supposed now - blend factor is 0.5 in both cases, not 0.75 as from the input
876          * vertices
877          */
878         hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
879         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
880         hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
881         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
882
883         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
884         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
885         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
886         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
887         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad1, 4, 0);
888         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
889
890         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTALPHA);
891         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
892         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVDESTALPHA);
893         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
894         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad2, 4, 0);
895         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
896
897         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
898         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
899         set_the_same_viewport_again(device);
900
901         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
902          * Disable alpha blending for the final composition
903          */
904         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
905         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
906
907         hr = IDirect3DDevice7_SetTexture(device, 0, offscreen);
908         ok(hr == D3D_OK, "IDirect3DDevice7_SetTexture failed, hr = %08x\n", hr);
909         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, composite_quad, 4, 0);
910         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
911         hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
912         ok(hr == D3D_OK, "IDirect3DDevice7_SetTexture failed, hr = %08x\n", hr);
913
914         hr = IDirect3DDevice7_EndScene(device);
915         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
916     }
917
918     color = getPixelColor(device, 160, 360);
919     red =   (color & 0x00ff0000) >> 16;
920     green = (color & 0x0000ff00) >>  8;
921     blue =  (color & 0x000000ff);
922     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
923        "SRCALPHA on frame buffer returned color 0x%08x, expected 0x00bf4000\n", color);
924
925     color = getPixelColor(device, 160, 120);
926     red =   (color & 0x00ff0000) >> 16;
927     green = (color & 0x0000ff00) >>  8;
928     blue =  (color & 0x000000ff);
929     ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff ,
930        "DSTALPHA on frame buffer returned color 0x%08x, expected 0x000000ff\n", color);
931
932     color = getPixelColor(device, 480, 360);
933     red =   (color & 0x00ff0000) >> 16;
934     green = (color & 0x0000ff00) >>  8;
935     blue =  (color & 0x000000ff);
936     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
937        "SRCALPHA on texture returned color 0x%08x, expected 0x00bf4000\n", color);
938
939     color = getPixelColor(device, 480, 120);
940     red =   (color & 0x00ff0000) >> 16;
941     green = (color & 0x0000ff00) >>  8;
942     blue =  (color & 0x000000ff);
943     ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81,
944        "DSTALPHA on texture returned color 0x%08x, expected 0x00800080\n", color);
945
946     out:
947     if(offscreen) IDirectDrawSurface7_Release(offscreen);
948     if(backbuffer) IDirectDrawSurface7_Release(backbuffer);
949 }
950
951 static void rhw_zero_test(IDirect3DDevice7 *device)
952 {
953 /* Test if it will render a quad correctly when vertex rhw = 0 */
954     HRESULT hr;
955     DWORD color;
956
957     struct {
958         float x, y, z;
959         float rhw;
960         DWORD diffuse;
961         } quad1[] =
962     {
963         {0, 100, 0, 0, 0xffffffff},
964         {0, 0, 0, 0, 0xffffffff},
965         {100, 100, 0, 0, 0xffffffff},
966         {100, 0, 0, 0, 0xffffffff},
967     };
968
969     /* Clear to black */
970     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0, 0);
971     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
972
973     hr = IDirect3DDevice7_BeginScene(device);
974     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
975
976     if (SUCCEEDED(hr)) {
977         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad1, 4, 0);
978         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
979
980         hr = IDirect3DDevice7_EndScene(device);
981         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
982     }
983
984     color = getPixelColor(device, 5, 5);
985     ok(color == 0xffffff ||
986        broken(color == 0), /* VMware */
987        "Got color %08x, expected 00ffffff\n", color);
988
989     color = getPixelColor(device, 105, 105);
990     ok(color == 0, "Got color %08x, expected 00000000\n", color);
991 }
992
993 static BOOL D3D1_createObjects(void)
994 {
995     WNDCLASS wc = {0};
996     HRESULT hr;
997     DDSURFACEDESC ddsd;
998     D3DEXECUTEBUFFERDESC exdesc;
999     D3DVIEWPORT vp_data;
1000
1001     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
1002     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
1003
1004     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
1005     if (FAILED(hr)) {
1006         return FALSE;
1007     }
1008
1009     wc.lpfnWndProc = DefWindowProc;
1010     wc.lpszClassName = "texturemapblend_test_wc";
1011     RegisterClass(&wc);
1012     window = CreateWindow("texturemapblend_test_wc", "texturemapblend_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1013
1014     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1015     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
1016     if(FAILED(hr)) {
1017         return FALSE;
1018     }
1019
1020     hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 32);
1021     if(FAILED(hr)) {
1022         /* 24 bit is fine too */
1023         hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 24);
1024     }
1025     ok(hr==DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode returned: %x\n", hr);
1026     if (FAILED(hr)) {
1027         return FALSE;
1028     }
1029
1030     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
1031     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
1032     if (FAILED(hr)) {
1033         return FALSE;
1034     }
1035
1036     memset(&ddsd, 0, sizeof(ddsd));
1037     ddsd.dwSize = sizeof(ddsd);
1038     ddsd.dwFlags = DDSD_CAPS;
1039     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
1040     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
1041     ok(hr==DD_OK, "CreateSurface returned: %x\n", hr);
1042     if (FAILED(hr)) {
1043         return FALSE;
1044     }
1045
1046     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **) &Direct3DDevice1);
1047     if(FAILED(hr)) {
1048         trace("Creating a HAL device failed, trying Ref\n");
1049         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRefDevice, (void **) &Direct3DDevice1);
1050     }
1051     ok(hr==D3D_OK, "Creating 3D device returned: %x\n", hr);
1052     if(FAILED(hr)) {
1053         return FALSE;
1054     }
1055
1056     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
1057     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
1058     if (FAILED(hr)) {
1059         return FALSE;
1060     }
1061
1062     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
1063     ok(hr == D3D_OK || hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
1064     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
1065     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1066     vp_data.dwSize = sizeof(vp_data);
1067     vp_data.dwX = 0;
1068     vp_data.dwY = 0;
1069     vp_data.dwWidth = 640;
1070     vp_data.dwHeight = 480;
1071     vp_data.dvScaleX = 1;
1072     vp_data.dvScaleY = 1;
1073     vp_data.dvMaxX = 640;
1074     vp_data.dvMaxY = 480;
1075     vp_data.dvMinZ = 0;
1076     vp_data.dvMaxZ = 1;
1077     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1078     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1079
1080     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1081     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1082     exdesc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1083     exdesc.dwBufferSize = 512;
1084     exdesc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1085     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &exdesc, &ExecuteBuffer, NULL);
1086     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed with %08x\n", hr);
1087     if (FAILED(hr)) {
1088         return FALSE;
1089     }
1090
1091     return TRUE;
1092 }
1093
1094 static void D3D1_releaseObjects(void)
1095 {
1096     if(ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1097     if(Surface1) IDirectDrawSurface_Release(Surface1);
1098     if(Viewport) IDirect3DViewport_Release(Viewport);
1099     if(Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1100     if(Direct3D1) IDirect3D_Release(Direct3D1);
1101     if(DirectDraw1) IDirectDraw_Release(DirectDraw1);
1102     if(window) DestroyWindow(window);
1103 }
1104
1105 static DWORD D3D1_getPixelColor(IDirectDraw *DirectDraw1, IDirectDrawSurface *Surface, UINT x, UINT y)
1106 {
1107     DWORD ret;
1108     HRESULT hr;
1109     DDSURFACEDESC ddsd;
1110     RECT rectToLock = {x, y, x+1, y+1};
1111     IDirectDrawSurface *surf = NULL;
1112
1113     /* Some implementations seem to dislike direct locking on the front buffer. Thus copy the front buffer
1114      * to an offscreen surface and lock it instead of the front buffer
1115      */
1116     memset(&ddsd, 0, sizeof(ddsd));
1117     ddsd.dwSize = sizeof(ddsd);
1118     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1119     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
1120     ddsd.dwWidth = 640;
1121     ddsd.dwHeight = 480;
1122     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
1123     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
1124     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed with %08x\n", hr);
1125     if(!surf)
1126     {
1127         trace("cannot create helper surface\n");
1128         return 0xdeadbeef;
1129     }
1130
1131     memset(&ddsd, 0, sizeof(ddsd));
1132     ddsd.dwSize = sizeof(ddsd);
1133     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1134
1135     hr = IDirectDrawSurface_BltFast(surf, 0, 0, Surface, NULL, 0);
1136     ok(hr == DD_OK, "IDirectDrawSurface_BltFast returned %08x\n", hr);
1137     if(FAILED(hr))
1138     {
1139         trace("Cannot blit\n");
1140         ret = 0xdeadbee;
1141         goto out;
1142     }
1143
1144     hr = IDirectDrawSurface_Lock(surf, &rectToLock, &ddsd, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
1145     if(FAILED(hr))
1146     {
1147         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
1148         ret = 0xdeadbeec;
1149         goto out;
1150     }
1151
1152     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
1153      * really important for these tests
1154      */
1155     ret = ((DWORD *) ddsd.lpSurface)[0] & 0x00ffffff;
1156     hr = IDirectDrawSurface_Unlock(surf, NULL);
1157     if(FAILED(hr))
1158     {
1159         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
1160     }
1161
1162 out:
1163     IDirectDrawSurface_Release(surf);
1164     return ret;
1165 }
1166
1167 #define EXEBUF_START_RENDER_STATES(count, ptr) do {\
1168                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_STATERENDER;\
1169                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DSTATE);\
1170                          ((D3DINSTRUCTION*)(ptr))->wCount = count;\
1171                          ptr = ((D3DINSTRUCTION*)(ptr))+1; } while (0)
1172
1173 #define EXEBUF_PUT_RENDER_STATE(state, value, ptr) do {\
1174                          U1(*((D3DSTATE*)(ptr))).drstRenderStateType = state; \
1175                          U2(*((D3DSTATE*)(ptr))).dwArg[0] = value; \
1176                          ptr = ((D3DSTATE*)(ptr))+1; } while (0)
1177
1178 #define EXEBUF_PUT_PROCESSVERTICES(nvertices, ptr) do {\
1179                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_PROCESSVERTICES;\
1180                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DPROCESSVERTICES);\
1181                          ((D3DINSTRUCTION*)(ptr))->wCount = 1;\
1182                          ptr = ((D3DINSTRUCTION*)(ptr))+1;\
1183                          ((D3DPROCESSVERTICES*)(ptr))->dwFlags = D3DPROCESSVERTICES_COPY;\
1184                          ((D3DPROCESSVERTICES*)(ptr))->wStart = 0;\
1185                          ((D3DPROCESSVERTICES*)(ptr))->wDest = 0;\
1186                          ((D3DPROCESSVERTICES*)(ptr))->dwCount = nvertices;\
1187                          ((D3DPROCESSVERTICES*)(ptr))->dwReserved = 0;\
1188                          ptr = ((D3DPROCESSVERTICES*)(ptr))+1; } while (0)
1189
1190 #define EXEBUF_END(ptr) do {\
1191                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_EXIT;\
1192                          ((D3DINSTRUCTION*)(ptr))->bSize = 0;\
1193                          ((D3DINSTRUCTION*)(ptr))->wCount = 0;\
1194                          ptr = ((D3DINSTRUCTION*)(ptr))+1; } while (0)
1195
1196 #define EXEBUF_PUT_QUAD(base_idx, ptr) do {\
1197                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_TRIANGLE;\
1198                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DTRIANGLE);\
1199                          ((D3DINSTRUCTION*)(ptr))->wCount = 2;\
1200                          ptr = ((D3DINSTRUCTION*)(ptr))+1;\
1201                          U1(*((D3DTRIANGLE*)(ptr))).v1 = base_idx;\
1202                          U2(*((D3DTRIANGLE*)(ptr))).v2 = (base_idx) + 1; \
1203                          U3(*((D3DTRIANGLE*)(ptr))).v3 = (base_idx) + 3; \
1204                          ((D3DTRIANGLE*)(ptr))->wFlags = 0;\
1205                          ptr = ((D3DTRIANGLE*)ptr)+1;\
1206                          U1(*((D3DTRIANGLE*)(ptr))).v1 = (base_idx) + 1; \
1207                          U2(*((D3DTRIANGLE*)(ptr))).v2 = (base_idx) + 2; \
1208                          U3(*((D3DTRIANGLE*)(ptr))).v3 = (base_idx) + 3; \
1209                          ((D3DTRIANGLE*)(ptr))->wFlags = 0;\
1210                          ptr = ((D3DTRIANGLE*)(ptr))+1;\
1211                         } while (0)
1212
1213 static HRESULT CALLBACK TextureFormatEnumCallback(LPDDSURFACEDESC lpDDSD, LPVOID lpContext)
1214 {
1215     if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
1216         *(BOOL*)lpContext = TRUE;
1217     }
1218
1219     return DDENUMRET_OK;
1220 }
1221
1222 static void D3D1_TextureMapBlendTest(void)
1223 {
1224     HRESULT hr;
1225     DDSURFACEDESC ddsd;
1226     D3DEXECUTEBUFFERDESC exdesc;
1227     D3DEXECUTEDATA exdata;
1228     DDBLTFX ddbltfx;
1229     RECT rect = { 0, 0, 64, 128 };
1230     DWORD color, red, blue, green;
1231     void *exe_buffer_ptr;
1232     DWORD exe_length;
1233     D3DTEXTUREHANDLE htex;
1234     DDCOLORKEY clrKey;
1235     IDirectDrawSurface *TexSurface = NULL;
1236     IDirect3DTexture *Texture = NULL;
1237     IDirectDrawPalette *Palette = NULL;
1238     PALETTEENTRY table1[256];
1239     BOOL p8_textures_supported = FALSE;
1240
1241     struct {
1242         float x, y, z;
1243         float rhw;
1244         DWORD diffuse;
1245         DWORD specular;
1246         float tu, tv;
1247         } test1_quads[] =
1248     {
1249           {0.0f,   0.0f,     0.0f, 1.0f, 0xffffffff, 0, 0.0f, 0.0f},
1250           {640.0f, 0.0f,     0.0f, 1.0f, 0xffffffff, 0, 1.0f, 0.0f},
1251           {640.0f, 240.0f,   0.0f, 1.0f, 0xffffffff, 0, 1.0f, 1.0f},
1252           {0.0f,   240.0f,   0.0f, 1.0f, 0xffffffff, 0, 0.0f, 1.0f},
1253           {0.0f,   240.0f,   0.0f, 1.0f, 0x80ffffff, 0, 0.0f, 0.0f},
1254           {640.0f, 240.0f,   0.0f, 1.0f, 0x80ffffff, 0, 1.0f, 0.0f},
1255           {640.0f, 480.0f,   0.0f, 1.0f, 0x80ffffff, 0, 1.0f, 1.0f},
1256           {0.0f,   480.0f,   0.0f, 1.0f, 0x80ffffff, 0, 0.0f, 1.0f}
1257     },  test2_quads[] =
1258           {
1259           {0.0f,   0.0f,     0.0f, 1.0f, 0x00ff0080, 0, 0.0f, 0.0f},
1260           {640.0f, 0.0f,     0.0f, 1.0f, 0x00ff0080, 0, 1.0f, 0.0f},
1261           {640.0f, 240.0f,   0.0f, 1.0f, 0x00ff0080, 0, 1.0f, 1.0f},
1262           {0.0f,   240.0f,   0.0f, 1.0f, 0x00ff0080, 0, 0.0f, 1.0f},
1263           {0.0f,   240.0f,   0.0f, 1.0f, 0x008000ff, 0, 0.0f, 0.0f},
1264           {640.0f, 240.0f,   0.0f, 1.0f, 0x008000ff, 0, 1.0f, 0.0f},
1265           {640.0f, 480.0f,   0.0f, 1.0f, 0x008000ff, 0, 1.0f, 1.0f},
1266           {0.0f,   480.0f,   0.0f, 1.0f, 0x008000ff, 0, 0.0f, 1.0f}
1267     };
1268
1269     /* 1) Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel*/
1270     memset (&ddsd, 0, sizeof (ddsd));
1271     ddsd.dwSize = sizeof (ddsd);
1272     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1273     ddsd.dwHeight = 128;
1274     ddsd.dwWidth = 128;
1275     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1276     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1277     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1278     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1279     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1280     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1281     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1282     U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
1283     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1284     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1285     if (FAILED(hr)) {
1286         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1287         goto out;
1288     }
1289
1290     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1291                 (void *)&Texture);
1292     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1293     if (FAILED(hr)) {
1294         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1295         goto out;
1296     }
1297
1298     memset(&ddbltfx, 0, sizeof(ddbltfx));
1299     ddbltfx.dwSize = sizeof(ddbltfx);
1300     U5(ddbltfx).dwFillColor = 0;
1301     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1302     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1303
1304     U5(ddbltfx).dwFillColor = 0xff0000ff;
1305     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1306     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1307     U5(ddbltfx).dwFillColor = 0x800000ff;
1308     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1309     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1310
1311     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1312     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1313     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1314     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1315     if (FAILED(hr)) {
1316         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1317         goto out;
1318     }
1319
1320     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1321
1322     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1323
1324     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1325
1326     EXEBUF_START_RENDER_STATES(12, exe_buffer_ptr);
1327     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_CULLMODE,         D3DCULL_NONE,              exe_buffer_ptr);
1328     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ZENABLE,          FALSE,                     exe_buffer_ptr);
1329     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_FOGENABLE,        FALSE,                     exe_buffer_ptr);
1330     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_SPECULARENABLE,   FALSE,                     exe_buffer_ptr);
1331     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMAG,       D3DFILTER_NEAREST,         exe_buffer_ptr);
1332     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMIN,       D3DFILTER_NEAREST,         exe_buffer_ptr);
1333     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_FILLMODE  ,       D3DFILL_SOLID,             exe_buffer_ptr);
1334     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_SRCBLEND,         D3DBLEND_SRCALPHA,         exe_buffer_ptr);
1335     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_DESTBLEND,        D3DBLEND_INVSRCALPHA,      exe_buffer_ptr);
1336     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE,                      exe_buffer_ptr);
1337     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMAPBLEND,  D3DTBLEND_MODULATE,        exe_buffer_ptr);
1338     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1339     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1340     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1341
1342     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1343     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1344
1345     EXEBUF_END(exe_buffer_ptr);
1346
1347     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1348
1349     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1350     if (FAILED(hr)) {
1351         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1352     }
1353
1354     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1355     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1356     exdata.dwVertexCount = 8;
1357     exdata.dwInstructionOffset = 256;
1358     exdata.dwInstructionLength = exe_length;
1359     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1360     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1361
1362     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1363     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1364
1365     if (SUCCEEDED(hr)) {
1366         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1367         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1368         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1369         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1370     }
1371
1372     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1373     red =   (color & 0x00ff0000) >> 16;
1374     green = (color & 0x0000ff00) >>  8;
1375     blue =  (color & 0x000000ff);
1376     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1377
1378     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1379     red =   (color & 0x00ff0000) >> 16;
1380     green = (color & 0x0000ff00) >>  8;
1381     blue =  (color & 0x000000ff);
1382     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1383
1384     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1385     red =   (color & 0x00ff0000) >> 16;
1386     green = (color & 0x0000ff00) >>  8;
1387     blue =  (color & 0x000000ff);
1388     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1389
1390     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1391     red =   (color & 0x00ff0000) >> 16;
1392     green = (color & 0x0000ff00) >>  8;
1393     blue =  (color & 0x000000ff);
1394     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1395
1396     /* 2) Test alpha with texture that has no alpha channel - alpha should be taken from diffuse color */
1397     if(Texture) IDirect3DTexture_Release(Texture);
1398     Texture = NULL;
1399     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1400     TexSurface = NULL;
1401
1402     memset (&ddsd, 0, sizeof (ddsd));
1403     ddsd.dwSize = sizeof (ddsd);
1404     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1405     ddsd.dwHeight = 128;
1406     ddsd.dwWidth = 128;
1407     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1408     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1409     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
1410     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1411     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1412     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1413     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1414
1415     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1416     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1417     if (FAILED(hr)) {
1418         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1419         goto out;
1420     }
1421
1422     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1423                 (void *)&Texture);
1424     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1425     if (FAILED(hr)) {
1426         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1427         goto out;
1428     }
1429
1430     memset(&ddbltfx, 0, sizeof(ddbltfx));
1431     ddbltfx.dwSize = sizeof(ddbltfx);
1432     U5(ddbltfx).dwFillColor = 0;
1433     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1434     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1435
1436     U5(ddbltfx).dwFillColor = 0xff0000ff;
1437     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1438     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1439     U5(ddbltfx).dwFillColor = 0x800000ff;
1440     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1441     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1442
1443     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1444     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1445     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1446     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1447     if (FAILED(hr)) {
1448         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1449         goto out;
1450     }
1451
1452     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1453
1454     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1455
1456     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1457
1458     EXEBUF_START_RENDER_STATES(1, exe_buffer_ptr);
1459     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1460     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1461     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1462
1463     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1464     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1465
1466     EXEBUF_END(exe_buffer_ptr);
1467
1468     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1469
1470     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1471     if (FAILED(hr)) {
1472         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1473     }
1474
1475     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1476     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1477     exdata.dwVertexCount = 8;
1478     exdata.dwInstructionOffset = 256;
1479     exdata.dwInstructionLength = exe_length;
1480     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1481     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1482
1483     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1484     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1485
1486     if (SUCCEEDED(hr)) {
1487         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1488         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1489         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1490         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1491     }
1492
1493     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1494     red =   (color & 0x00ff0000) >> 16;
1495     green = (color & 0x0000ff00) >>  8;
1496     blue =  (color & 0x000000ff);
1497     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1498
1499     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1500     red =   (color & 0x00ff0000) >> 16;
1501     green = (color & 0x0000ff00) >>  8;
1502     blue =  (color & 0x000000ff);
1503     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1504
1505     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1506     red =   (color & 0x00ff0000) >> 16;
1507     green = (color & 0x0000ff00) >>  8;
1508     blue =  (color & 0x000000ff);
1509     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1510
1511     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1512     red =   (color & 0x00ff0000) >> 16;
1513     green = (color & 0x0000ff00) >>  8;
1514     blue =  (color & 0x000000ff);
1515     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1516
1517     /* 3) Test RGB - should multiply color components from diffuse color and texture */
1518     if(Texture) IDirect3DTexture_Release(Texture);
1519     Texture = NULL;
1520     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1521     TexSurface = NULL;
1522
1523     memset (&ddsd, 0, sizeof (ddsd));
1524     ddsd.dwSize = sizeof (ddsd);
1525     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1526     ddsd.dwHeight = 128;
1527     ddsd.dwWidth = 128;
1528     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1529     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1530     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1531     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1532     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1533     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1534     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1535     U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
1536     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1537     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1538     if (FAILED(hr)) {
1539         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1540         goto out;
1541     }
1542
1543     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1544                 (void *)&Texture);
1545     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1546     if (FAILED(hr)) {
1547         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1548         goto out;
1549     }
1550
1551     memset(&ddbltfx, 0, sizeof(ddbltfx));
1552     ddbltfx.dwSize = sizeof(ddbltfx);
1553     U5(ddbltfx).dwFillColor = 0;
1554     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1555     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1556
1557     U5(ddbltfx).dwFillColor = 0x00ffffff;
1558     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1559     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1560     U5(ddbltfx).dwFillColor = 0x00ffff80;
1561     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1562     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1563
1564     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1565     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1566     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1567     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1568     if (FAILED(hr)) {
1569         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1570         goto out;
1571     }
1572
1573     memcpy(exdesc.lpData, test2_quads, sizeof(test2_quads));
1574
1575     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1576
1577     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1578
1579     EXEBUF_START_RENDER_STATES(2, exe_buffer_ptr);
1580     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE, exe_buffer_ptr);
1581     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1582     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1583     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1584
1585     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1586     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1587
1588     EXEBUF_END(exe_buffer_ptr);
1589
1590     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1591
1592     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1593     if (FAILED(hr)) {
1594         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1595     }
1596
1597     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1598     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1599     exdata.dwVertexCount = 8;
1600     exdata.dwInstructionOffset = 256;
1601     exdata.dwInstructionLength = exe_length;
1602     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1603     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1604
1605     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1606     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1607
1608     if (SUCCEEDED(hr)) {
1609         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1610         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1611         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1612         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1613     }
1614
1615     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1616     red =   (color & 0x00ff0000) >> 16;
1617     green = (color & 0x0000ff00) >>  8;
1618     blue =  (color & 0x000000ff);
1619     ok(red == 0xff &&  green == 0 && blue >= 0x3e && blue <= 0x42, "Got color %08x, expected 00ff0040 or near\n", color);
1620
1621     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1622     red =   (color & 0x00ff0000) >> 16;
1623     green = (color & 0x0000ff00) >>  8;
1624     blue =  (color & 0x000000ff);
1625     ok(red == 0xff &&  green == 0 && blue == 0x80, "Got color %08x, expected 00ff0080 or near\n", color);
1626
1627     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1628     red =   (color & 0x00ff0000) >> 16;
1629     green = (color & 0x0000ff00) >>  8;
1630     blue =  (color & 0x000000ff);
1631     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0x80, "Got color %08x, expected 00800080 or near\n", color);
1632
1633     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1634     red =   (color & 0x00ff0000) >> 16;
1635     green = (color & 0x0000ff00) >>  8;
1636     blue =  (color & 0x000000ff);
1637     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0xff, "Got color %08x, expected 008000ff or near\n", color);
1638
1639     /* 4) Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere) */
1640     if(Texture) IDirect3DTexture_Release(Texture);
1641     Texture = NULL;
1642     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1643     TexSurface = NULL;
1644
1645     memset (&ddsd, 0, sizeof (ddsd));
1646     ddsd.dwSize = sizeof (ddsd);
1647     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1648     ddsd.dwHeight = 128;
1649     ddsd.dwWidth = 128;
1650     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1651     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1652     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
1653     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 16;
1654     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0xf800;
1655     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x07e0;
1656     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x001f;
1657
1658     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1659     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1660     if (FAILED(hr)) {
1661         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1662         goto out;
1663     }
1664
1665     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1666                 (void *)&Texture);
1667     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1668     if (FAILED(hr)) {
1669         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1670         goto out;
1671     }
1672
1673     memset(&ddbltfx, 0, sizeof(ddbltfx));
1674     ddbltfx.dwSize = sizeof(ddbltfx);
1675     U5(ddbltfx).dwFillColor = 0;
1676     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1677     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1678     U5(ddbltfx).dwFillColor = 0xf800;
1679     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1680     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1681     U5(ddbltfx).dwFillColor = 0x001f;
1682     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1683     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1684
1685     clrKey.dwColorSpaceLowValue = 0x001f;
1686     clrKey.dwColorSpaceHighValue = 0x001f;
1687     hr = IDirectDrawSurface_SetColorKey(TexSurface, DDCKEY_SRCBLT, &clrKey);
1688     ok(hr==D3D_OK, "IDirectDrawSurfac_SetColorKey returned: %x\n", hr);
1689
1690     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1691     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1692     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1693     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1694     if (FAILED(hr)) {
1695         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1696         goto out;
1697     }
1698
1699     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1700
1701     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1702
1703     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1704
1705     EXEBUF_START_RENDER_STATES(2, exe_buffer_ptr);
1706     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE, exe_buffer_ptr);
1707     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1708     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1709     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1710
1711     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1712     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1713
1714     EXEBUF_END(exe_buffer_ptr);
1715
1716     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1717
1718     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1719     if (FAILED(hr)) {
1720         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1721     }
1722
1723     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1724     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1725     exdata.dwVertexCount = 8;
1726     exdata.dwInstructionOffset = 256;
1727     exdata.dwInstructionLength = exe_length;
1728     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1729     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1730
1731     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1732     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1733
1734     if (SUCCEEDED(hr)) {
1735         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1736         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1737         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1738         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1739     }
1740
1741     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1742     ok(color == 0, "Got color %08x, expected 00000000\n", color);
1743
1744     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1745     red =   (color & 0x00ff0000) >> 16;
1746     green = (color & 0x0000ff00) >>  8;
1747     blue =  (color & 0x000000ff);
1748     ok(red == 0xff &&  green == 0 && blue == 0, "Got color %08x, expected 00ff0000 or near\n", color);
1749
1750     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1751     ok(color == 0, "Got color %08x, expected 00000000\n", color);
1752
1753     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1754     red =   (color & 0x00ff0000) >> 16;
1755     green = (color & 0x0000ff00) >>  8;
1756     blue =  (color & 0x000000ff);
1757     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0, "Got color %08x, expected 00800000 or near\n", color);
1758
1759     /* 5) Test alpha again, now with color keyed P8 texture */
1760     if(Texture) IDirect3DTexture_Release(Texture);
1761     Texture = NULL;
1762     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1763     TexSurface = NULL;
1764
1765     hr = IDirect3DDevice_EnumTextureFormats(Direct3DDevice1, TextureFormatEnumCallback,
1766                                                 &p8_textures_supported);
1767     ok(hr == DD_OK, "IDirect3DDevice_EnumTextureFormats returned %08x\n", hr);
1768
1769     if (!p8_textures_supported) {
1770         skip("device has no P8 texture support, skipping test\n");
1771     } else {
1772         memset (&ddsd, 0, sizeof (ddsd));
1773         ddsd.dwSize = sizeof (ddsd);
1774         ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1775         ddsd.dwHeight = 128;
1776         ddsd.dwWidth = 128;
1777         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1778         ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1779         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1780         U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 8;
1781
1782         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1783         ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1784         if (FAILED(hr)) {
1785             skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1786             goto out;
1787         }
1788
1789         memset(table1, 0, sizeof(table1));
1790         table1[0].peBlue = 0xff;
1791         table1[1].peRed = 0xff;
1792
1793         hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &Palette, NULL);
1794         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1795         if (FAILED(hr)) {
1796             skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1797             goto out;
1798         }
1799
1800         hr = IDirectDrawSurface_SetPalette(TexSurface, Palette);
1801         ok(hr==D3D_OK, "IDirectDrawSurface_SetPalette returned: %x\n", hr);
1802
1803         hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1804                     (void *)&Texture);
1805         ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1806         if (FAILED(hr)) {
1807             skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1808             goto out;
1809         }
1810
1811         memset(&ddbltfx, 0, sizeof(ddbltfx));
1812         ddbltfx.dwSize = sizeof(ddbltfx);
1813         U5(ddbltfx).dwFillColor = 0;
1814         hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1815         ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1816         U5(ddbltfx).dwFillColor = 0;
1817         hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1818         ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1819         U5(ddbltfx).dwFillColor = 1;
1820         hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1821         ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1822
1823         clrKey.dwColorSpaceLowValue = 1;
1824         clrKey.dwColorSpaceHighValue = 1;
1825         hr = IDirectDrawSurface_SetColorKey(TexSurface, DDCKEY_SRCBLT, &clrKey);
1826         ok(hr==D3D_OK, "IDirectDrawSurfac_SetColorKey returned: %x\n", hr);
1827
1828         memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1829         exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1830         hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1831         ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1832         if (FAILED(hr)) {
1833             skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1834             goto out;
1835         }
1836
1837         memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1838
1839         exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1840
1841         EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1842
1843         EXEBUF_START_RENDER_STATES(2, exe_buffer_ptr);
1844         EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE, exe_buffer_ptr);
1845         hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1846         ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1847         EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1848
1849         EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1850         EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1851
1852         EXEBUF_END(exe_buffer_ptr);
1853
1854         exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1855
1856         hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1857         if (FAILED(hr)) {
1858             trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1859         }
1860
1861         memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1862         exdata.dwSize = sizeof(D3DEXECUTEDATA);
1863         exdata.dwVertexCount = 8;
1864         exdata.dwInstructionOffset = 256;
1865         exdata.dwInstructionLength = exe_length;
1866         hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1867         ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1868
1869         hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1870         ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1871
1872         if (SUCCEEDED(hr)) {
1873             hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1874             ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1875             hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1876             ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1877         }
1878
1879         color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1880         ok(color == 0, "Got color %08x, expected 00000000\n", color);
1881
1882         color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1883         red =   (color & 0x00ff0000) >> 16;
1884         green = (color & 0x0000ff00) >>  8;
1885         blue =  (color & 0x000000ff);
1886         ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1887
1888         color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1889         ok(color == 0, "Got color %08x, expected 00000000\n", color);
1890
1891         color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1892         red =   (color & 0x00ff0000) >> 16;
1893         green = (color & 0x0000ff00) >>  8;
1894         blue =  (color & 0x000000ff);
1895         ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1896     }
1897
1898     out:
1899
1900     if (Palette) IDirectDrawPalette_Release(Palette);
1901     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1902     if (Texture) IDirect3DTexture_Release(Texture);
1903 }
1904
1905 static void D3D1_ViewportClearTest(void)
1906 {
1907     HRESULT hr;
1908     IDirect3DMaterial *bgMaterial = NULL;
1909     D3DMATERIAL mat;
1910     D3DMATERIALHANDLE hMat;
1911     D3DVIEWPORT vp_data;
1912     IDirect3DViewport *Viewport2 = NULL;
1913     DWORD color, red, green, blue;
1914
1915     hr = IDirect3D_CreateMaterial(Direct3D1, &bgMaterial, NULL);
1916     ok(hr == D3D_OK, "IDirect3D_CreateMaterial failed: %08x\n", hr);
1917     if (FAILED(hr)) {
1918         goto out;
1919     }
1920
1921     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport2, NULL);
1922     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
1923     if (FAILED(hr)) {
1924         goto out;
1925     }
1926
1927     hr = IDirect3DViewport_Initialize(Viewport2, Direct3D1);
1928     ok(hr == D3D_OK || hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
1929     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport2);
1930     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1931     vp_data.dwSize = sizeof(vp_data);
1932     vp_data.dwX = 200;
1933     vp_data.dwY = 200;
1934     vp_data.dwWidth = 100;
1935     vp_data.dwHeight = 100;
1936     vp_data.dvScaleX = 1;
1937     vp_data.dvScaleY = 1;
1938     vp_data.dvMaxX = 100;
1939     vp_data.dvMaxY = 100;
1940     vp_data.dvMinZ = 0;
1941     vp_data.dvMaxZ = 1;
1942     hr = IDirect3DViewport_SetViewport(Viewport2, &vp_data);
1943     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1944
1945     memset(&mat, 0, sizeof(mat));
1946     mat.dwSize = sizeof(mat);
1947     U1(U(mat).diffuse).r = 1.0f;
1948     hr = IDirect3DMaterial_SetMaterial(bgMaterial, &mat);
1949     ok(hr == D3D_OK, "IDirect3DMaterial_SetMaterial failed: %08x\n", hr);
1950
1951     hr = IDirect3DMaterial_GetHandle(bgMaterial, Direct3DDevice1, &hMat);
1952     ok(hr == D3D_OK, "IDirect3DMaterial_GetHandle failed: %08x\n", hr);
1953
1954     hr = IDirect3DViewport_SetBackground(Viewport, hMat);
1955     ok(hr == D3D_OK, "IDirect3DViewport_SetBackground failed: %08x\n", hr);
1956     hr = IDirect3DViewport_SetBackground(Viewport2, hMat);
1957     ok(hr == D3D_OK, "IDirect3DViewport_SetBackground failed: %08x\n", hr);
1958
1959     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1960     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1961
1962     if (SUCCEEDED(hr)) {
1963         D3DRECT rect;
1964
1965         U1(rect).x1 = U2(rect).y1 = 0;
1966         U3(rect).x2 = 640;
1967         U4(rect).y2 = 480;
1968
1969         hr = IDirect3DViewport_Clear(Viewport,  1,  &rect, D3DCLEAR_TARGET);
1970         ok(hr == D3D_OK, "IDirect3DViewport_Clear failed: %08x\n", hr);
1971
1972         memset(&mat, 0, sizeof(mat));
1973         mat.dwSize = sizeof(mat);
1974         U3(U(mat).diffuse).b = 1.0f;
1975         hr = IDirect3DMaterial_SetMaterial(bgMaterial, &mat);
1976         ok(hr == D3D_OK, "IDirect3DMaterial_SetMaterial failed: %08x\n", hr);
1977
1978         hr = IDirect3DViewport_Clear(Viewport2,  1,  &rect, D3DCLEAR_TARGET);
1979         ok(hr == D3D_OK, "IDirect3DViewport_Clear failed: %08x\n", hr);
1980
1981         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1982         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1983         }
1984
1985     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1986     red =   (color & 0x00ff0000) >> 16;
1987     green = (color & 0x0000ff00) >>  8;
1988     blue =  (color & 0x000000ff);
1989     ok((red == 0xff && green == 0 && blue == 0) ||
1990        broken(red == 0 && green == 0 && blue == 0xff), /* VMware and some native boxes */
1991        "Got color %08x, expected 00ff0000\n", color);
1992
1993     color = D3D1_getPixelColor(DirectDraw1, Surface1, 205, 205);
1994     red =   (color & 0x00ff0000) >> 16;
1995     green = (color & 0x0000ff00) >>  8;
1996     blue =  (color & 0x000000ff);
1997     ok(red == 0 && green == 0 && blue == 0xff, "Got color %08x, expected 000000ff\n", color);
1998
1999     out:
2000
2001     if (bgMaterial) IDirect3DMaterial_Release(bgMaterial);
2002     if (Viewport2) IDirect3DViewport_Release(Viewport2);
2003 }
2004
2005 static DWORD D3D3_getPixelColor(IDirectDraw4 *DirectDraw, IDirectDrawSurface4 *Surface, UINT x, UINT y)
2006 {
2007     DWORD ret;
2008     HRESULT hr;
2009     DDSURFACEDESC2 ddsd;
2010     RECT rectToLock = {x, y, x+1, y+1};
2011     IDirectDrawSurface4 *surf = NULL;
2012
2013     /* Some implementations seem to dislike direct locking on the front buffer. Thus copy the front buffer
2014      * to an offscreen surface and lock it instead of the front buffer
2015      */
2016     memset(&ddsd, 0, sizeof(ddsd));
2017     ddsd.dwSize = sizeof(ddsd);
2018     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2019     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
2020     ddsd.dwWidth = 640;
2021     ddsd.dwHeight = 480;
2022     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
2023     hr = IDirectDraw4_CreateSurface(DirectDraw, &ddsd, &surf, NULL);
2024     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed with %08x\n", hr);
2025     if(!surf)
2026     {
2027         trace("cannot create helper surface\n");
2028         return 0xdeadbeef;
2029     }
2030
2031     memset(&ddsd, 0, sizeof(ddsd));
2032     ddsd.dwSize = sizeof(ddsd);
2033     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2034
2035     hr = IDirectDrawSurface4_BltFast(surf, 0, 0, Surface, NULL, 0);
2036     ok(hr == DD_OK, "IDirectDrawSurface_BltFast returned %08x\n", hr);
2037     if(FAILED(hr))
2038     {
2039         trace("Cannot blit\n");
2040         ret = 0xdeadbee;
2041         goto out;
2042     }
2043
2044     hr = IDirectDrawSurface4_Lock(surf, &rectToLock, &ddsd, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
2045     if(FAILED(hr))
2046     {
2047         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
2048         ret = 0xdeadbeec;
2049         goto out;
2050     }
2051
2052     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
2053      * really important for these tests
2054      */
2055     ret = ((DWORD *) ddsd.lpSurface)[0] & 0x00ffffff;
2056     hr = IDirectDrawSurface4_Unlock(surf, NULL);
2057     if(FAILED(hr))
2058     {
2059         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
2060     }
2061
2062 out:
2063     IDirectDrawSurface4_Release(surf);
2064     return ret;
2065 }
2066
2067 static void D3D3_ViewportClearTest(void)
2068 {
2069     HRESULT hr;
2070     IDirectDraw *DirectDraw1 = NULL;
2071     IDirectDraw4 *DirectDraw4 = NULL;
2072     IDirectDrawSurface4 *Primary = NULL;
2073     IDirect3D3 *Direct3D3 = NULL;
2074     IDirect3DViewport3 *Viewport3 = NULL;
2075     IDirect3DViewport3 *SmallViewport3 = NULL;
2076     IDirect3DDevice3 *Direct3DDevice3 = NULL;
2077     WNDCLASS wc = {0};
2078     DDSURFACEDESC2 ddsd;
2079     D3DVIEWPORT2 vp_data;
2080     DWORD color, red, green, blue;
2081     D3DRECT rect;
2082     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
2083                       0.0f, 1.0f, 0.0f, 0.0f,
2084                       0.0f, 0.0f, 1.0f, 0.0f,
2085                       0.0f, 0.0f, 0.0f, 1.0f };
2086     struct vertex quad[] =
2087     {
2088         {-1.0f, -1.0f,   0.1f,                          0xffffffff},
2089         {-1.0f,  1.0f,   0.1f,                          0xffffffff},
2090         { 1.0f,  1.0f,   0.1f,                          0xffffffff},
2091         { 1.0f, -1.0f,   0.1f,                          0xffffffff},
2092     };
2093
2094     WORD Indices[] = {0, 1, 2, 2, 3, 0};
2095     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
2096
2097     wc.lpfnWndProc = DefWindowProc;
2098     wc.lpszClassName = "D3D3_ViewportClearTest_wc";
2099     RegisterClass(&wc);
2100     window = CreateWindow("D3D3_ViewportClearTest_wc", "D3D3_ViewportClearTest",
2101                             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2102
2103     hr = DirectDrawCreate( NULL, &DirectDraw1, NULL );
2104     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
2105     if(FAILED(hr)) goto out;
2106
2107     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2108     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
2109     if(FAILED(hr)) goto out;
2110
2111     hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 32);
2112     if(FAILED(hr)) {
2113         /* 24 bit is fine too */
2114         hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 24);
2115     }
2116     ok(hr==DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode returned: %x\n", hr);
2117     if (FAILED(hr)) goto out;
2118
2119     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void**)&DirectDraw4);
2120     ok(hr==DD_OK, "QueryInterface returned: %08x\n", hr);
2121     if(FAILED(hr)) goto out;
2122
2123     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2124     ddsd.dwSize = sizeof(DDSURFACEDESC2);
2125     ddsd.dwFlags    = DDSD_CAPS;
2126     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
2127
2128     hr = IDirectDraw_CreateSurface(DirectDraw4, &ddsd, &Primary, NULL);
2129     ok(hr==DD_OK, "IDirectDraw_CreateSurface returned: %08x\n", hr);
2130     if(FAILED(hr)) goto out;
2131
2132     hr = IDirectDraw4_QueryInterface(DirectDraw4, &IID_IDirect3D3, (void**)&Direct3D3);
2133     ok(hr==DD_OK, "IDirectDraw4_QueryInterface returned: %08x\n", hr);
2134     if(FAILED(hr)) goto out;
2135
2136     hr = IDirect3D3_CreateDevice(Direct3D3, &IID_IDirect3DHALDevice, Primary, &Direct3DDevice3, NULL);
2137     if(FAILED(hr)) {
2138         trace("Creating a HAL device failed, trying Ref\n");
2139         hr = IDirect3D3_CreateDevice(Direct3D3, &IID_IDirect3DRefDevice, Primary, &Direct3DDevice3, NULL);
2140     }
2141     ok(hr==D3D_OK, "Creating 3D device returned: %x\n", hr);
2142     if(FAILED(hr)) goto out;
2143
2144     hr = IDirect3D3_CreateViewport(Direct3D3, &Viewport3, NULL);
2145     ok(hr==DD_OK, "IDirect3D3_CreateViewport returned: %08x\n", hr);
2146     if(FAILED(hr)) goto out;
2147
2148     hr = IDirect3DDevice3_AddViewport(Direct3DDevice3, Viewport3);
2149     ok(hr==DD_OK, "IDirect3DDevice3_AddViewport returned: %08x\n", hr);
2150
2151     memset(&vp_data, 0, sizeof(D3DVIEWPORT2));
2152     vp_data.dwSize = sizeof(D3DVIEWPORT2);
2153     vp_data.dwWidth = 640;
2154     vp_data.dwHeight = 480;
2155     vp_data.dvClipX = -1.0f;
2156     vp_data.dvClipWidth = 2.0f;
2157     vp_data.dvClipY = 1.0f;
2158     vp_data.dvClipHeight = 2.0f;
2159     vp_data.dvMaxZ = 1.0f;
2160     hr = IDirect3DViewport3_SetViewport2(Viewport3, &vp_data);
2161     ok(hr==DD_OK, "IDirect3DViewport3_SetViewport2 returned: %08x\n", hr);
2162
2163     hr = IDirect3D3_CreateViewport(Direct3D3, &SmallViewport3, NULL);
2164     ok(hr==DD_OK, "IDirect3D3_CreateViewport returned: %08x\n", hr);
2165     if(FAILED(hr)) goto out;
2166
2167     hr = IDirect3DDevice3_AddViewport(Direct3DDevice3, SmallViewport3);
2168     ok(hr==DD_OK, "IDirect3DDevice3_AddViewport returned: %08x\n", hr);
2169
2170     memset(&vp_data, 0, sizeof(D3DVIEWPORT2));
2171     vp_data.dwSize = sizeof(D3DVIEWPORT2);
2172     vp_data.dwX = 400;
2173     vp_data.dwY = 100;
2174     vp_data.dwWidth = 100;
2175     vp_data.dwHeight = 100;
2176     vp_data.dvClipX = -1.0f;
2177     vp_data.dvClipWidth = 2.0f;
2178     vp_data.dvClipY = 1.0f;
2179     vp_data.dvClipHeight = 2.0f;
2180     vp_data.dvMaxZ = 1.0f;
2181     hr = IDirect3DViewport3_SetViewport2(SmallViewport3, &vp_data);
2182     ok(hr==DD_OK, "IDirect3DViewport3_SetViewport2 returned: %08x\n", hr);
2183
2184     hr = IDirect3DDevice3_BeginScene(Direct3DDevice3);
2185     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
2186
2187     hr = IDirect3DDevice3_SetTransform(Direct3DDevice3, D3DTRANSFORMSTATE_WORLD, (D3DMATRIX *) mat);
2188     ok(hr == D3D_OK, "IDirect3DDevice3_SetTransform returned %08x\n", hr);
2189     hr = IDirect3DDevice3_SetTransform(Direct3DDevice3, D3DTRANSFORMSTATE_VIEW, (D3DMATRIX *)mat);
2190     ok(hr == D3D_OK, "IDirect3DDevice3_SetTransform returned %08x\n", hr);
2191     hr = IDirect3DDevice3_SetTransform(Direct3DDevice3, D3DTRANSFORMSTATE_PROJECTION, (D3DMATRIX *) mat);
2192     ok(hr == D3D_OK, "IDirect3DDevice3_SetTransform returned %08x\n", hr);
2193     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_CLIPPING, FALSE);
2194     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2195     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_ZENABLE, FALSE);
2196     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2197     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_FOGENABLE, FALSE);
2198     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2199     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_STENCILENABLE, FALSE);
2200     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2201     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
2202     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2203     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
2204     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2205     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
2206     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState failed with %08x\n", hr);
2207     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_LIGHTING, FALSE);
2208     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2209
2210     if (SUCCEEDED(hr)) {
2211         U1(rect).x1 = U2(rect).y1 = 0;
2212         U3(rect).x2 = 640;
2213         U4(rect).y2 = 480;
2214
2215         hr = IDirect3DViewport3_Clear2(Viewport3, 1, &rect, D3DCLEAR_TARGET, 0x00ff00, 0.0f, 0);
2216         ok(hr == D3D_OK, "IDirect3DViewport3_Clear2 failed, hr = %08x\n", hr);
2217
2218         hr = IDirect3DViewport3_Clear2(SmallViewport3, 1, &rect, D3DCLEAR_TARGET, 0xff0000, 0.0f, 0);
2219         ok(hr == D3D_OK, "IDirect3DViewport3_Clear2 failed, hr = %08x\n", hr);
2220
2221         hr = IDirect3DDevice3_EndScene(Direct3DDevice3);
2222         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
2223         }
2224
2225     color = D3D3_getPixelColor(DirectDraw4, Primary, 5, 5);
2226     red =   (color & 0x00ff0000) >> 16;
2227     green = (color & 0x0000ff00) >>  8;
2228     blue =  (color & 0x000000ff);
2229     ok(red == 0 && green == 0xff && blue == 0, "Got color %08x, expected 0000ff00\n", color);
2230
2231     color = D3D3_getPixelColor(DirectDraw4, Primary, 405, 105);
2232     red =   (color & 0x00ff0000) >> 16;
2233     green = (color & 0x0000ff00) >>  8;
2234     blue =  (color & 0x000000ff);
2235     ok(red == 0xff && green == 0 && blue == 0, "Got color %08x, expected 00ff0000\n", color);
2236
2237     /* Test that clearing viewport doesn't interfere with rendering to previously active viewport. */
2238     hr = IDirect3DDevice3_BeginScene(Direct3DDevice3);
2239     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
2240
2241     if (SUCCEEDED(hr)) {
2242         hr = IDirect3DDevice3_SetCurrentViewport(Direct3DDevice3, SmallViewport3);
2243         ok(hr == D3D_OK, "IDirect3DDevice3_SetCurrentViewport failed with %08x\n", hr);
2244
2245         hr = IDirect3DViewport3_Clear2(Viewport3, 1, &rect, D3DCLEAR_TARGET, 0x000000, 0.0f, 0);
2246         ok(hr == D3D_OK, "IDirect3DViewport3_Clear2 failed, hr = %08x\n", hr);
2247
2248         hr = IDirect3DDevice3_DrawIndexedPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, fvf, quad, 4 /* NumVerts */,
2249                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
2250         ok(hr == D3D_OK, "IDirect3DDevice3_DrawIndexedPrimitive failed with %08x\n", hr);
2251
2252         hr = IDirect3DDevice3_EndScene(Direct3DDevice3);
2253         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
2254         }
2255
2256     color = D3D3_getPixelColor(DirectDraw4, Primary, 5, 5);
2257     red =   (color & 0x00ff0000) >> 16;
2258     green = (color & 0x0000ff00) >>  8;
2259     blue =  (color & 0x000000ff);
2260     ok(red == 0 && green == 0 && blue == 0, "Got color %08x, expected 00000000\n", color);
2261
2262     color = D3D3_getPixelColor(DirectDraw4, Primary, 405, 105);
2263     red =   (color & 0x00ff0000) >> 16;
2264     green = (color & 0x0000ff00) >>  8;
2265     blue =  (color & 0x000000ff);
2266     ok(red == 0xff && green == 0xff && blue == 0xff, "Got color %08x, expected 00ffffff\n", color);
2267
2268     out:
2269
2270     if (SmallViewport3) IDirect3DViewport3_Release(SmallViewport3);
2271     if (Viewport3) IDirect3DViewport3_Release(Viewport3);
2272     if (Direct3DDevice3) IDirect3DDevice3_Release(Direct3DDevice3);
2273     if (Direct3D3) IDirect3D3_Release(Direct3D3);
2274     if (Primary) IDirectDrawSurface4_Release(Primary);
2275     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
2276     if (DirectDraw4) IDirectDraw4_Release(DirectDraw4);
2277     if(window) DestroyWindow(window);
2278 }
2279
2280 static void p8_surface_fill_rect(IDirectDrawSurface *dest, UINT x, UINT y, UINT w, UINT h, BYTE colorindex)
2281 {
2282     DDSURFACEDESC ddsd;
2283     HRESULT hr;
2284     UINT i, i1;
2285     BYTE *p;
2286
2287     memset(&ddsd, 0, sizeof(ddsd));
2288     ddsd.dwSize = sizeof(ddsd);
2289
2290     hr = IDirectDrawSurface_Lock(dest, NULL, &ddsd, DDLOCK_WRITEONLY | DDLOCK_WAIT, NULL);
2291     ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2292
2293     p = (BYTE *)ddsd.lpSurface + U1(ddsd).lPitch * y + x;
2294
2295     for (i = 0; i < h; i++) {
2296         for (i1 = 0; i1 < w; i1++) {
2297             p[i1] = colorindex;
2298         }
2299         p += U1(ddsd).lPitch;
2300     }
2301
2302     hr = IDirectDrawSurface_Unlock(dest, NULL);
2303     ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2304 }
2305
2306 static COLORREF getPixelColor_GDI(IDirectDrawSurface *Surface, UINT x, UINT y)
2307 {
2308     COLORREF clr = CLR_INVALID;
2309     HDC hdc;
2310     HRESULT hr;
2311
2312     hr = IDirectDrawSurface_GetDC(Surface, &hdc);
2313     ok(hr==DD_OK, "IDirectDrawSurface_GetDC returned: %x\n", hr);
2314
2315     if (SUCCEEDED(hr)) {
2316         clr = GetPixel(hdc, x, y);
2317
2318         hr = IDirectDrawSurface_ReleaseDC(Surface, hdc);
2319         ok(hr==DD_OK, "IDirectDrawSurface_ReleaseDC returned: %x\n", hr);
2320     }
2321
2322     return clr;
2323 }
2324
2325 static BOOL colortables_check_equality(PALETTEENTRY table1[256], RGBQUAD table2[256])
2326 {
2327     int i;
2328
2329     for (i = 0; i < 256; i++) {
2330        if (table1[i].peRed != table2[i].rgbRed || table1[i].peGreen != table2[i].rgbGreen ||
2331            table1[i].peBlue != table2[i].rgbBlue) return FALSE;
2332     }
2333
2334     return TRUE;
2335 }
2336
2337 static void p8_primary_test(void)
2338 {
2339     /* Test 8bit mode used by games like StarCraft, C&C Red Alert I etc */
2340     DDSURFACEDESC ddsd;
2341     HDC hdc;
2342     HRESULT hr;
2343     PALETTEENTRY entries[256];
2344     RGBQUAD coltable[256];
2345     UINT i, i1, i2;
2346     IDirectDrawPalette *ddprimpal = NULL;
2347     IDirectDrawSurface *offscreen = NULL;
2348     WNDCLASS wc = {0};
2349     DDBLTFX ddbltfx;
2350     COLORREF color;
2351     RECT rect;
2352     DDCOLORKEY clrKey;
2353     unsigned differences;
2354
2355     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
2356     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
2357
2358     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
2359     if (FAILED(hr)) {
2360         goto out;
2361     }
2362
2363     wc.lpfnWndProc = DefWindowProc;
2364     wc.lpszClassName = "p8_primary_test_wc";
2365     RegisterClass(&wc);
2366     window = CreateWindow("p8_primary_test_wc", "p8_primary_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2367
2368     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2369     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
2370     if(FAILED(hr)) {
2371         goto out;
2372     }
2373
2374     hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 8);
2375     ok(hr==DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode returned: %x\n", hr);
2376     if (FAILED(hr)) {
2377         goto out;
2378     }
2379
2380     memset(&ddsd, 0, sizeof(ddsd));
2381     ddsd.dwSize = sizeof(ddsd);
2382     ddsd.dwFlags = DDSD_CAPS;
2383     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2384     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
2385     ok(hr==DD_OK, "CreateSurface returned: %x\n", hr);
2386     if (FAILED(hr)) {
2387         goto out;
2388     }
2389
2390     memset(entries, 0, sizeof(entries));
2391     entries[0].peRed = 0xff;
2392     entries[1].peGreen = 0xff;
2393     entries[2].peBlue = 0xff;
2394
2395     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, entries, &ddprimpal, NULL);
2396     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2397     if (FAILED(hr)) {
2398         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
2399         goto out;
2400     }
2401
2402     hr = IDirectDrawSurface_SetPalette(Surface1, ddprimpal);
2403     ok(hr==DD_OK, "IDirectDrawSurface_SetPalette returned: %x\n", hr);
2404
2405     p8_surface_fill_rect(Surface1, 0, 0, 640, 480, 2);
2406
2407     color = getPixelColor_GDI(Surface1, 10, 10);
2408     ok(GetRValue(color) == 0 && GetGValue(color) == 0 && GetBValue(color) == 0xFF,
2409             "got R %02X G %02X B %02X, expected R 00 G 00 B FF\n",
2410             GetRValue(color), GetGValue(color), GetBValue(color));
2411
2412     memset(&ddbltfx, 0, sizeof(ddbltfx));
2413     ddbltfx.dwSize = sizeof(ddbltfx);
2414     U5(ddbltfx).dwFillColor = 0;
2415     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2416     ok(hr == DD_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
2417
2418     color = getPixelColor_GDI(Surface1, 10, 10);
2419     ok(GetRValue(color) == 0xFF && GetGValue(color) == 0 && GetBValue(color) == 0,
2420             "got R %02X G %02X B %02X, expected R FF G 00 B 00\n",
2421             GetRValue(color), GetGValue(color), GetBValue(color));
2422
2423     memset(&ddbltfx, 0, sizeof(ddbltfx));
2424     ddbltfx.dwSize = sizeof(ddbltfx);
2425     U5(ddbltfx).dwFillColor = 1;
2426     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2427     ok(hr == DD_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
2428
2429     color = getPixelColor_GDI(Surface1, 10, 10);
2430     ok(GetRValue(color) == 0 && GetGValue(color) == 0xFF && GetBValue(color) == 0,
2431             "got R %02X G %02X B %02X, expected R 00 G FF B 00\n",
2432             GetRValue(color), GetGValue(color), GetBValue(color));
2433
2434     memset (&ddsd, 0, sizeof (ddsd));
2435     ddsd.dwSize = sizeof (ddsd);
2436     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
2437     ddsd.dwWidth = 16;
2438     ddsd.dwHeight = 16;
2439     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
2440     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
2441     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2442     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 8;
2443     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &offscreen, NULL);
2444     ok(hr == DD_OK ||
2445        broken(hr == DDERR_INVALIDPIXELFORMAT) || /* VMware */
2446        broken(hr == DDERR_NODIRECTDRAWHW), /* VMware */
2447        "IDirectDraw_CreateSurface returned %08x\n", hr);
2448     if (FAILED(hr)) goto out;
2449
2450     memset(entries, 0, sizeof(entries));
2451     for (i = 0; i < 256; i++) {
2452         entries[i].peBlue = i;
2453         }
2454     hr = IDirectDrawPalette_SetEntries(ddprimpal, 0, 0, 256, entries);
2455     ok(hr == DD_OK, "IDirectDrawPalette_SetEntries failed with %08x\n", hr);
2456
2457     hr = IDirectDrawSurface_GetDC(offscreen, &hdc);
2458     ok(hr==DD_OK, "IDirectDrawSurface_GetDC returned: %x\n", hr);
2459     i = GetDIBColorTable(hdc, 0, 256, coltable);
2460     ok(i == 256, "GetDIBColorTable returned %u, last error: %x\n", i, GetLastError());
2461     hr = IDirectDrawSurface_ReleaseDC(offscreen, hdc);
2462     ok(hr==DD_OK, "IDirectDrawSurface_ReleaseDC returned: %x\n", hr);
2463
2464     ok(colortables_check_equality(entries, coltable), "unexpected colortable on offscreen surface\n");
2465
2466     p8_surface_fill_rect(offscreen, 0, 0, 16, 16, 2);
2467
2468     memset(entries, 0, sizeof(entries));
2469     entries[0].peRed = 0xff;
2470     entries[1].peGreen = 0xff;
2471     entries[2].peBlue = 0xff;
2472     entries[3].peRed = 0x80;
2473     hr = IDirectDrawPalette_SetEntries(ddprimpal, 0, 0, 256, entries);
2474     ok(hr == DD_OK, "IDirectDrawPalette_SetEntries failed with %08x\n", hr);
2475
2476     hr = IDirectDrawSurface_BltFast(Surface1, 0, 0, offscreen, NULL, 0);
2477     ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2478
2479     color = getPixelColor_GDI(Surface1, 1, 1);
2480     ok(GetRValue(color) == 0 && GetGValue(color) == 0x00 && GetBValue(color) == 0xFF,
2481             "got R %02X G %02X B %02X, expected R 00 G 00 B FF\n",
2482             GetRValue(color), GetGValue(color), GetBValue(color));
2483
2484     /* Color keyed blit. */
2485     p8_surface_fill_rect(offscreen, 0, 0, 8, 8, 3);
2486     clrKey.dwColorSpaceLowValue = 3;
2487     clrKey.dwColorSpaceHighValue = 3;
2488     hr = IDirectDrawSurface_SetColorKey(offscreen, DDCKEY_SRCBLT, &clrKey);
2489     ok(hr==D3D_OK, "IDirectDrawSurfac_SetColorKey returned: %x\n", hr);
2490
2491     hr = IDirectDrawSurface_BltFast(Surface1, 100, 100, offscreen, NULL, DDBLTFAST_SRCCOLORKEY);
2492     ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2493
2494     color = getPixelColor_GDI(Surface1, 105, 105);
2495     ok(GetRValue(color) == 0 && GetGValue(color) == 0xFF && GetBValue(color) == 0,
2496             "got R %02X G %02X B %02X, expected R 00 G FF B 00\n",
2497             GetRValue(color), GetGValue(color), GetBValue(color));
2498
2499     color = getPixelColor_GDI(Surface1, 112, 112);
2500     ok(GetRValue(color) == 0 && GetGValue(color) == 0x00 && GetBValue(color) == 0xFF,
2501             "got R %02X G %02X B %02X, expected R 00 G 00 B FF\n",
2502             GetRValue(color), GetGValue(color), GetBValue(color));
2503
2504     rect.left = 100;
2505     rect.top = 200;
2506     rect.right = 116;
2507     rect.bottom = 216;
2508
2509     memset(&ddbltfx, 0, sizeof(ddbltfx));
2510     ddbltfx.dwSize = sizeof(ddbltfx);
2511     ddbltfx.ddckSrcColorkey.dwColorSpaceLowValue = ddbltfx.ddckSrcColorkey.dwColorSpaceHighValue = 2;
2512     hr = IDirectDrawSurface_Blt(Surface1, &rect, offscreen, NULL,
2513         DDBLT_WAIT | DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &ddbltfx);
2514     ok(hr==DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned: %x\n", hr);
2515     hr = IDirectDrawSurface_Blt(Surface1, &rect, offscreen, NULL,
2516         DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &ddbltfx);
2517     ok(hr==DD_OK, "IDirectDrawSurface_Blt returned: %x\n", hr);
2518
2519     color = getPixelColor_GDI(Surface1, 105, 205);
2520     ok(GetRValue(color) == 0x80 && GetGValue(color) == 0 && GetBValue(color) == 0,
2521             "got R %02X G %02X B %02X, expected R 80 G 00 B 00\n",
2522             GetRValue(color), GetGValue(color), GetBValue(color));
2523
2524     color = getPixelColor_GDI(Surface1, 112, 212);
2525     ok(GetRValue(color) == 0 && GetGValue(color) == 0xFF && GetBValue(color) == 0,
2526             "got R %02X G %02X B %02X, expected R 00 G FF B 00\n",
2527             GetRValue(color), GetGValue(color), GetBValue(color));
2528
2529     /* Test blitting and locking patterns that are likely to trigger bugs in opengl renderer (p8
2530        surface conversion and uploading/downloading to/from opengl texture). Similar patterns (
2531        blitting front buffer areas to/from an offscreen surface mixed with locking) are used by C&C
2532        Red Alert I. */
2533     IDirectDrawSurface_Release(offscreen);
2534
2535     memset (&ddsd, 0, sizeof (ddsd));
2536     ddsd.dwSize = sizeof (ddsd);
2537     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
2538     ddsd.dwWidth = 640;
2539     ddsd.dwHeight = 480;
2540     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
2541     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
2542     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2543     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 8;
2544     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &offscreen, NULL);
2545     ok(hr == DD_OK, "IDirectDraw_CreateSurface returned %08x\n", hr);
2546
2547     if (FAILED(hr)) goto out;
2548
2549     /* Test two times, first time front buffer has a palette and second time front buffer
2550        has no palette; the latter is somewhat contrived example, but an app could set
2551        front buffer palette later. */
2552     for (i2 = 0; i2 < 2; i2++) {
2553         if (i2 == 1) {
2554             hr = IDirectDrawSurface_SetPalette(Surface1, NULL);
2555             ok(hr==DD_OK, "IDirectDrawSurface_SetPalette returned: %x\n", hr);
2556         }
2557
2558         memset(&ddsd, 0, sizeof(ddsd));
2559         ddsd.dwSize = sizeof(ddsd);
2560         hr = IDirectDrawSurface_Lock(Surface1, NULL, &ddsd, DDLOCK_WAIT, NULL);
2561         ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2562
2563         for (i = 0; i < 256; i++) {
2564             unsigned x = (i % 128) * 4;
2565             unsigned y = (i / 128) * 4;
2566             BYTE *p = (BYTE *)ddsd.lpSurface + U1(ddsd).lPitch * y + x;
2567
2568             for (i1 = 0; i1 < 4; i1++) {
2569                 p[0] = p[1] = p[2] = p[3] = i;
2570                 p += U1(ddsd).lPitch;
2571             }
2572         }
2573
2574         hr = IDirectDrawSurface_Unlock(Surface1, NULL);
2575         ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2576
2577         hr = IDirectDrawSurface_BltFast(offscreen, 0, 0, Surface1, NULL, 0);
2578         ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2579
2580         /* This ensures offscreen surface contents will be downloaded to system memory. */
2581         memset(&ddsd, 0, sizeof(ddsd));
2582         ddsd.dwSize = sizeof(ddsd);
2583         hr = IDirectDrawSurface_Lock(offscreen, NULL, &ddsd, DDLOCK_WAIT, NULL);
2584         ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2585         hr = IDirectDrawSurface_Unlock(offscreen, NULL);
2586         ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2587
2588         /* Offscreen surface data will have to be converted and uploaded to texture. */
2589         rect.left = 0;
2590         rect.top = 0;
2591         rect.right = 16;
2592         rect.bottom = 16;
2593         hr = IDirectDrawSurface_BltFast(offscreen, 600, 400, Surface1, &rect, 0);
2594         ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2595
2596         /* This ensures offscreen surface contents will be downloaded to system memory. */
2597         memset(&ddsd, 0, sizeof(ddsd));
2598         ddsd.dwSize = sizeof(ddsd);
2599         hr = IDirectDrawSurface_Lock(offscreen, NULL, &ddsd, DDLOCK_WAIT, NULL);
2600         ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2601         hr = IDirectDrawSurface_Unlock(offscreen, NULL);
2602         ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2603
2604         hr = IDirectDrawSurface_BltFast(Surface1, 0, 0, offscreen, NULL, 0);
2605         ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2606
2607         memset(&ddsd, 0, sizeof(ddsd));
2608         ddsd.dwSize = sizeof(ddsd);
2609         hr = IDirectDrawSurface_Lock(Surface1, NULL, &ddsd, DDLOCK_WAIT, NULL);
2610         ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2611
2612         differences = 0;
2613
2614         for (i = 0; i < 256; i++) {
2615             unsigned x = (i % 128) * 4 + 1;
2616             unsigned y = (i / 128) * 4 + 1;
2617             BYTE *p = (BYTE *)ddsd.lpSurface + U1(ddsd).lPitch * y + x;
2618
2619             if (*p != i) differences++;
2620         }
2621
2622         hr = IDirectDrawSurface_Unlock(Surface1, NULL);
2623         ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2624
2625         ok(differences == 0, i2 == 0 ? "Pass 1. Unexpected front buffer contents after blit (%u differences)\n" :
2626                 "Pass 2 (with NULL front buffer palette). Unexpected front buffer contents after blit (%u differences)\n",
2627                 differences);
2628     }
2629
2630     out:
2631
2632     if(ddprimpal) IDirectDrawPalette_Release(ddprimpal);
2633     if(offscreen) IDirectDrawSurface_Release(offscreen);
2634     if(Surface1) IDirectDrawSurface_Release(Surface1);
2635     if(DirectDraw1) IDirectDraw_Release(DirectDraw1);
2636     if(window) DestroyWindow(window);
2637 }
2638
2639 static void cubemap_test(IDirect3DDevice7 *device)
2640 {
2641     IDirect3D7 *d3d;
2642     IDirectDraw7 *ddraw;
2643     IDirectDrawSurface7 *cubemap, *surface;
2644     D3DDEVICEDESC7 d3dcaps;
2645     HRESULT hr;
2646     DWORD color;
2647     DDSURFACEDESC2 ddsd;
2648     DDBLTFX DDBltFx;
2649     DDSCAPS2 caps;
2650     static float quad[] = {
2651       -1.0,   -1.0,    0.1,    1.0,    0.0,    0.0, /* Lower left */
2652        0.0,   -1.0,    0.1,    1.0,    0.0,    0.0,
2653       -1.0,    0.0,    0.1,    1.0,    0.0,    0.0,
2654        0.0,    0.0,    0.1,    1.0,    0.0,    0.0,
2655
2656        0.0,   -1.0,    0.1,    0.0,    1.0,    0.0, /* Lower right */
2657        1.0,   -1.0,    0.1,    0.0,    1.0,    0.0,
2658        0.0,    0.0,    0.1,    0.0,    1.0,    0.0,
2659        1.0,    0.0,    0.1,    0.0,    1.0,    0.0,
2660
2661        0.0,    0.0,    0.1,    0.0,    0.0,    1.0, /* upper right */
2662        1.0,    0.0,    0.1,    0.0,    0.0,    1.0,
2663        0.0,    1.0,    0.1,    0.0,    0.0,    1.0,
2664        1.0,    1.0,    0.1,    0.0,    0.0,    1.0,
2665
2666       -1.0,    0.0,    0.1,   -1.0,    0.0,    0.0, /* Upper left */
2667        0.0,    0.0,    0.1,   -1.0,    0.0,    0.0,
2668       -1.0,    1.0,    0.1,   -1.0,    0.0,    0.0,
2669        0.0,    1.0,    0.1,   -1.0,    0.0,    0.0,
2670     };
2671
2672     memset(&DDBltFx, 0, sizeof(DDBltFx));
2673     DDBltFx.dwSize = sizeof(DDBltFx);
2674
2675     memset(&d3dcaps, 0, sizeof(d3dcaps));
2676     hr = IDirect3DDevice7_GetCaps(device, &d3dcaps);
2677     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
2678     if(!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
2679     {
2680         skip("No cubemap support\n");
2681         return;
2682     }
2683
2684     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
2685     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
2686
2687     hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
2688     ok(hr == D3D_OK, "IDirect3DDevice7_GetDirect3D returned %08x\n", hr);
2689     hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
2690     ok(hr == D3D_OK, "IDirect3D7_QueryInterface returned %08x\n", hr);
2691     IDirect3D7_Release(d3d);
2692
2693
2694     memset(&ddsd, 0, sizeof(ddsd));
2695     ddsd.dwSize = sizeof(ddsd);
2696     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2697     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
2698     ddsd.dwWidth = 16;
2699     ddsd.dwHeight = 16;
2700     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2701     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
2702     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2703     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2704     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2705     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2706     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2707
2708     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &cubemap, NULL);
2709     ok(hr == DD_OK, "IDirectDraw7_CreateSurface returned %08x\n", hr);
2710     IDirectDraw7_Release(ddraw);
2711
2712     /* Positive X */
2713     U5(DDBltFx).dwFillColor = 0x00ff0000;
2714     hr = IDirectDrawSurface7_Blt(cubemap, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2715     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2716
2717     memset(&caps, 0, sizeof(caps));
2718     caps.dwCaps = DDSCAPS_TEXTURE;
2719     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX;
2720     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2721     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2722     U5(DDBltFx).dwFillColor = 0x0000ffff;
2723     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2724     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2725
2726     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ;
2727     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2728     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2729     U5(DDBltFx).dwFillColor = 0x0000ff00;
2730     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2731     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2732
2733     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ;
2734     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2735     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2736     U5(DDBltFx).dwFillColor = 0x000000ff;
2737     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2738     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2739
2740     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY;
2741     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2742     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2743     U5(DDBltFx).dwFillColor = 0x00ffff00;
2744     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2745     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2746
2747     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY;
2748     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2749     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2750     U5(DDBltFx).dwFillColor = 0x00ff00ff;
2751     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2752     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2753
2754     hr = IDirect3DDevice7_SetTexture(device, 0, cubemap);
2755     ok(hr == DD_OK, "IDirect3DDevice7_SetTexture returned %08x\n", hr);
2756     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
2757     ok(hr == DD_OK, "IDirect3DDevice7_SetTextureStageState returned %08x\n", hr);
2758     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
2759     ok(hr == DD_OK, "IDirect3DDevice7_SetTextureStageState returned %08x\n", hr);
2760
2761     hr = IDirect3DDevice7_BeginScene(device);
2762     ok(hr == DD_OK, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
2763     if(SUCCEEDED(hr))
2764     {
2765         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, quad + 0 * 6, 4, 0);
2766         if (hr == DDERR_UNSUPPORTED || hr == DDERR_NODIRECTDRAWHW)
2767         {
2768             /* VMware */
2769             win_skip("IDirect3DDevice7_DrawPrimitive is not completely implemented, colors won't be tested\n");
2770             hr = IDirect3DDevice7_EndScene(device);
2771             ok(hr == DD_OK, "IDirect3DDevice7_EndScene returned %08x\n", hr);
2772             goto out;
2773         }
2774         ok(hr == DD_OK, "IDirect3DDevice7_DrawPrimitive returned %08x\n", hr);
2775         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, quad + 4 * 6, 4, 0);
2776         ok(hr == DD_OK, "IDirect3DDevice7_DrawPrimitive returned %08x\n", hr);
2777         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, quad + 8 * 6, 4, 0);
2778         ok(hr == DD_OK, "IDirect3DDevice7_DrawPrimitive returned %08x\n", hr);
2779         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, quad + 12* 6, 4, 0);
2780         ok(hr == DD_OK, "IDirect3DDevice7_DrawPrimitive returned %08x\n", hr);
2781
2782         hr = IDirect3DDevice7_EndScene(device);
2783         ok(hr == DD_OK, "IDirect3DDevice7_EndScene returned %08x\n", hr);
2784     }
2785     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
2786     ok(hr == DD_OK, "IDirect3DDevice7_SetTextureStageState returned %08x\n", hr);
2787
2788     color = getPixelColor(device, 160, 360); /* lower left quad - positivex */
2789     ok(color == 0x00ff0000, "DDSCAPS2_CUBEMAP_POSITIVEX has color 0x%08x, expected 0x00ff0000\n", color);
2790     color = getPixelColor(device, 160, 120); /* upper left quad - negativex */
2791     ok(color == 0x0000ffff, "DDSCAPS2_CUBEMAP_NEGATIVEX has color 0x%08x, expected 0x0000ffff\n", color);
2792     color = getPixelColor(device, 480, 360); /* lower right quad - positivey */
2793     ok(color == 0x00ff00ff, "DDSCAPS2_CUBEMAP_POSITIVEY has color 0x%08x, expected 0x00ff00ff\n", color);
2794     color = getPixelColor(device, 480, 120); /* upper right quad - positivez */
2795     ok(color == 0x000000ff, "DDSCAPS2_CUBEMAP_POSITIVEZ has color 0x%08x, expected 0x000000ff\n", color);
2796
2797 out:
2798     hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
2799     ok(hr == DD_OK, "IDirect3DDevice7_SetTexture returned %08x\n", hr);
2800     IDirectDrawSurface7_Release(cubemap);
2801 }
2802
2803 /* This test tests depth clamping / clipping behaviour:
2804  *   - When D3DRS_CLIPPING is disabled depth values are *clamped* to the
2805  *   minimum/maximum z value.
2806  *   - The viewport's MinZ/MaxZ is irrelevant for this.
2807  *   - When D3DRS_CLIPPING is enabled depth values are clipped.
2808  *   - Pretransformed vertices behave the same as regular vertices.
2809  */
2810 static void depth_clamp_test(IDirect3DDevice7 *device)
2811 {
2812     struct tvertex quad1[] =
2813     {
2814         {    0,    0,  5.0f, 1.0, 0xff002b7f},
2815         {  640,    0,  5.0f, 1.0, 0xff002b7f},
2816         {    0,  480,  5.0f, 1.0, 0xff002b7f},
2817         {  640,  480,  5.0f, 1.0, 0xff002b7f},
2818     };
2819     struct tvertex quad2[] =
2820     {
2821         {    0,  300, 10.0f, 1.0, 0xfff9e814},
2822         {  640,  300, 10.0f, 1.0, 0xfff9e814},
2823         {    0,  360, 10.0f, 1.0, 0xfff9e814},
2824         {  640,  360, 10.0f, 1.0, 0xfff9e814},
2825     };
2826     struct vertex quad3[] =
2827     {
2828         {-0.65, 0.55,  5.0f,      0xffffffff},
2829         {-0.35, 0.55,  5.0f,      0xffffffff},
2830         {-0.65, 0.15,  5.0f,      0xffffffff},
2831         {-0.35, 0.15,  5.0f,      0xffffffff},
2832     };
2833     struct vertex quad4[] =
2834     {
2835         {-0.87, 0.83, 10.0f,      0xffffffff},
2836         {-0.65, 0.83, 10.0f,      0xffffffff},
2837         {-0.87, 0.55, 10.0f,      0xffffffff},
2838         {-0.65, 0.55, 10.0f,      0xffffffff},
2839     };
2840     struct vertex quad5[] =
2841     {
2842         { -0.5,  0.5, 10.0f,      0xff14f914},
2843         {  0.5,  0.5, 10.0f,      0xff14f914},
2844         { -0.5, -0.5, 10.0f,      0xff14f914},
2845         {  0.5, -0.5, 10.0f,      0xff14f914},
2846     };
2847     struct tvertex quad6[] =
2848     {
2849         {    0,  120, 10.0f, 1.0, 0xfff91414},
2850         {  640,  120, 10.0f, 1.0, 0xfff91414},
2851         {    0,  180, 10.0f, 1.0, 0xfff91414},
2852         {  640,  180, 10.0f, 1.0, 0xfff91414},
2853     };
2854
2855     D3DVIEWPORT7 vp;
2856     D3DCOLOR color;
2857     HRESULT hr;
2858
2859     vp.dwX = 0;
2860     vp.dwY = 0;
2861     vp.dwWidth = 640;
2862     vp.dwHeight = 480;
2863     vp.dvMinZ = 0.0;
2864     vp.dvMaxZ = 7.5;
2865
2866     hr = IDirect3DDevice7_SetViewport(device, &vp);
2867     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
2868
2869     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0, 0);
2870     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2871
2872     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
2873     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2874     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
2875     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2876     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZWRITEENABLE, TRUE);
2877     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2878     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
2879     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2880
2881     hr = IDirect3DDevice7_BeginScene(device);
2882     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2883
2884     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad1, 4, 0);
2885     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2886     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad2, 4, 0);
2887     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2888     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad3, 4, 0);
2889     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2890     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad4, 4, 0);
2891     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2892
2893     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, TRUE);
2894     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2895
2896     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad5, 4, 0);
2897     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2898     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad6, 4, 0);
2899     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2900
2901     hr = IDirect3DDevice7_EndScene(device);
2902     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2903
2904     color = getPixelColor(device, 75, 75);
2905     ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
2906     color = getPixelColor(device, 150, 150);
2907     ok(color_match(color, 0x00ffffff, 1) ||
2908        broken(color == 0x00f91414), /* Reference rasterizer */
2909        "color 0x%08x.\n", color);
2910     color = getPixelColor(device, 320, 240);
2911     ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);
2912     color = getPixelColor(device, 320, 330);
2913     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
2914     color = getPixelColor(device, 320, 330);
2915     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
2916
2917     vp.dvMinZ = 0.0;
2918     vp.dvMaxZ = 1.0;
2919     hr = IDirect3DDevice7_SetViewport(device, &vp);
2920     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
2921 }
2922
2923 static void DX1_BackBufferFlipTest(void)
2924 {
2925     HRESULT hr;
2926     IDirectDraw *DirectDraw1 = NULL;
2927     IDirectDrawSurface *Primary = NULL;
2928     IDirectDrawSurface *Backbuffer = NULL;
2929     WNDCLASS wc = {0};
2930     DDSURFACEDESC ddsd;
2931     DDBLTFX ddbltfx;
2932     COLORREF color;
2933     const DWORD white = 0xffffff;
2934     const DWORD red = 0xff0000;
2935     BOOL attached = FALSE;
2936
2937     wc.lpfnWndProc = DefWindowProc;
2938     wc.lpszClassName = "DX1_BackBufferFlipTest_wc";
2939     RegisterClass(&wc);
2940     window = CreateWindow("DX1_BackBufferFlipTest_wc", "DX1_BackBufferFlipTest",
2941                             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2942
2943     hr = DirectDrawCreate( NULL, &DirectDraw1, NULL );
2944     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
2945     if(FAILED(hr)) goto out;
2946
2947     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2948     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
2949     if(FAILED(hr)) goto out;
2950
2951     hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 32);
2952     if(FAILED(hr)) {
2953         /* 24 bit is fine too */
2954         hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 24);
2955     }
2956     ok(hr==DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode returned: %x\n", hr);
2957     if (FAILED(hr)) {
2958         goto out;
2959     }
2960
2961     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
2962     ddsd.dwSize = sizeof(DDSURFACEDESC);
2963     ddsd.dwFlags = DDSD_CAPS;
2964     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2965
2966     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Primary, NULL);
2967     ok(hr==DD_OK, "IDirectDraw_CreateSurface returned: %08x\n", hr);
2968
2969     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
2970     ddsd.dwSize = sizeof(DDSURFACEDESC);
2971     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2972     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
2973     ddsd.dwWidth = 640;
2974     ddsd.dwHeight = 480;
2975     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
2976     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
2977     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
2978     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
2979     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
2980     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
2981
2982     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Backbuffer, NULL);
2983     ok(hr==DD_OK, "IDirectDraw_CreateSurface returned: %08x\n", hr);
2984     if(FAILED(hr)) goto out;
2985
2986     hr = IDirectDrawSurface_AddAttachedSurface(Primary, Backbuffer);
2987     todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
2988        "Attaching a back buffer to a front buffer returned %08x\n", hr);
2989     if (FAILED(hr)) goto out;
2990
2991     attached = TRUE;
2992
2993     memset(&ddbltfx, 0, sizeof(ddbltfx));
2994     ddbltfx.dwSize = sizeof(ddbltfx);
2995     U5(ddbltfx).dwFillColor = red;
2996     hr = IDirectDrawSurface_Blt(Backbuffer, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2997     ok(hr == DD_OK, "IDirectDrawSurface_Blt returned: %x\n", hr);
2998
2999     U5(ddbltfx).dwFillColor = white;
3000     hr = IDirectDrawSurface_Blt(Primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
3001     ok(hr == DD_OK, "IDirectDrawSurface_Blt returned: %x\n", hr);
3002
3003     /* Check it out */
3004     color = getPixelColor_GDI(Primary, 5, 5);
3005     ok(GetRValue(color) == 0xFF && GetGValue(color) == 0xFF && GetBValue(color) == 0xFF,
3006             "got R %02X G %02X B %02X, expected R FF G FF B FF\n",
3007             GetRValue(color), GetGValue(color), GetBValue(color));
3008
3009     color = getPixelColor_GDI(Backbuffer, 5, 5);
3010     ok(GetRValue(color) == 0xFF && GetGValue(color) == 0 && GetBValue(color) == 0,
3011             "got R %02X G %02X B %02X, expected R FF G 00 B 00\n",
3012             GetRValue(color), GetGValue(color), GetBValue(color));
3013
3014     hr = IDirectDrawSurface_Flip(Primary, NULL, DDFLIP_WAIT);
3015     todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3016
3017     if (hr == DD_OK)
3018     {
3019         color = getPixelColor_GDI(Primary, 5, 5);
3020         ok(GetRValue(color) == 0xFF && GetGValue(color) == 0 && GetBValue(color) == 0,
3021                 "got R %02X G %02X B %02X, expected R FF G 00 B 00\n",
3022                 GetRValue(color), GetGValue(color), GetBValue(color));
3023
3024         color = getPixelColor_GDI(Backbuffer, 5, 5);
3025         ok((GetRValue(color) == 0xFF && GetGValue(color) == 0xFF && GetBValue(color) == 0xFF) ||
3026            broken(GetRValue(color) == 0xFF && GetGValue(color) == 0 && GetBValue(color) == 0),  /* broken driver */
3027                 "got R %02X G %02X B %02X, expected R FF G FF B FF\n",
3028                 GetRValue(color), GetGValue(color), GetBValue(color));
3029     }
3030
3031     out:
3032
3033     if (Backbuffer)
3034     {
3035         if (attached)
3036             IDirectDrawSurface_DeleteAttachedSurface(Primary, 0, Backbuffer);
3037         IDirectDrawSurface_Release(Backbuffer);
3038     }
3039     if (Primary) IDirectDrawSurface_Release(Primary);
3040     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
3041     if (window) DestroyWindow(window);
3042 }
3043
3044 START_TEST(visual)
3045 {
3046     HRESULT hr;
3047     DWORD color;
3048     if(!createObjects())
3049     {
3050         skip("Cannot initialize DirectDraw and Direct3D, skipping\n");
3051         return;
3052     }
3053
3054     /* Check for the reliability of the returned data */
3055     hr = IDirect3DDevice7_Clear(Direct3DDevice, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
3056     if(FAILED(hr))
3057     {
3058         skip("Clear failed, can't assure correctness of the test results, skipping\n");
3059         goto cleanup;
3060     }
3061
3062     color = getPixelColor(Direct3DDevice, 1, 1);
3063     if(color !=0x00ff0000)
3064     {
3065         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
3066         goto cleanup;
3067     }
3068
3069     hr = IDirect3DDevice7_Clear(Direct3DDevice, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
3070     if(FAILED(hr))
3071     {
3072         skip("Clear failed, can't assure correctness of the test results, skipping\n");
3073         goto cleanup;
3074     }
3075
3076     color = getPixelColor(Direct3DDevice, 639, 479);
3077     if(color != 0x0000ddee)
3078     {
3079         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
3080         goto cleanup;
3081     }
3082
3083     /* Now run the tests */
3084     blt_test(Direct3DDevice);
3085     depth_clamp_test(Direct3DDevice);
3086     lighting_test(Direct3DDevice);
3087     clear_test(Direct3DDevice);
3088     fog_test(Direct3DDevice);
3089     offscreen_test(Direct3DDevice);
3090     alpha_test(Direct3DDevice);
3091     rhw_zero_test(Direct3DDevice);
3092     cubemap_test(Direct3DDevice);
3093
3094     releaseObjects(); /* release DX7 interfaces to test D3D1 */
3095
3096     if(!D3D1_createObjects()) {
3097         skip("Cannot initialize D3D1, skipping\n");
3098     }
3099     else {
3100         D3D1_TextureMapBlendTest();
3101         D3D1_ViewportClearTest();
3102     }
3103     D3D1_releaseObjects();
3104
3105     D3D3_ViewportClearTest();
3106     p8_primary_test();
3107     DX1_BackBufferFlipTest();
3108
3109     return ;
3110
3111 cleanup:
3112     releaseObjects();
3113 }