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