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