urlmon: Don't create stgmed_obj for binding to object.
[wine] / dlls / ddraw / tests / visual.c
1 /*
2  * Copyright (C) 2007 Stefan Dösinger(for CodeWeavers)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 /* See comment in dlls/d3d9/tests/visual.c for general guidelines */
20
21 #include <assert.h>
22 #include "wine/test.h"
23 #include "ddraw.h"
24 #include "d3d.h"
25
26 HWND window;
27 IDirectDraw7        *DirectDraw = NULL;
28 IDirectDrawSurface7 *Surface;
29 IDirect3D7          *Direct3D = NULL;
30 IDirect3DDevice7    *Direct3DDevice = NULL;
31
32 IDirectDraw *DirectDraw1 = NULL;
33 IDirectDrawSurface *Surface1 = NULL;
34 IDirect3D *Direct3D1 = NULL;
35 IDirect3DDevice *Direct3DDevice1 = NULL;
36 IDirect3DExecuteBuffer *ExecuteBuffer = NULL;
37 IDirect3DViewport *Viewport = NULL;
38
39 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
40
41 static BOOL createObjects(void)
42 {
43     HRESULT hr;
44     HMODULE hmod = GetModuleHandleA("ddraw.dll");
45     WNDCLASS wc = {0};
46     DDSURFACEDESC2 ddsd;
47
48
49     if(!hmod) return FALSE;
50     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
51     if(!pDirectDrawCreateEx) return FALSE;
52
53     hr = pDirectDrawCreateEx(NULL, (void **) &DirectDraw, &IID_IDirectDraw7, NULL);
54     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", hr);
55     if(!DirectDraw) goto err;
56
57     wc.lpfnWndProc = &DefWindowProc;
58     wc.lpszClassName = "d3d7_test_wc";
59     RegisterClass(&wc);
60     window = CreateWindow("d3d7_test_wc", "d3d7_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
61
62     hr = IDirectDraw7_SetCooperativeLevel(DirectDraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
63     ok(hr == DD_OK, "IDirectDraw7_SetCooperativeLevel failed with %08x\n", hr);
64     if(FAILED(hr)) goto err;
65     hr = IDirectDraw7_SetDisplayMode(DirectDraw, 640, 480, 32, 0, 0);
66     if(FAILED(hr)) {
67         /* 24 bit is fine too */
68         hr = IDirectDraw7_SetDisplayMode(DirectDraw, 640, 480, 24, 0, 0);
69
70     }
71     ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "IDirectDraw7_SetDisplayMode failed with %08x\n", hr);
72     if(FAILED(hr)) {
73         /* use trace, the caller calls skip() */
74         trace("SetDisplayMode failed\n");
75         goto err;
76     }
77
78     hr = IDirectDraw7_QueryInterface(DirectDraw, &IID_IDirect3D7, (void**) &Direct3D);
79     if (hr == E_NOINTERFACE) goto err;
80     ok(hr==DD_OK, "QueryInterface returned: %08x\n", hr);
81
82     /* DirectDraw Flipping behavior doesn't seem that well-defined. The reference rasterizer behaves differently
83      * than hardware implementations. Request single buffering, that seems to work everywhere
84      */
85     memset(&ddsd, 0, sizeof(ddsd));
86     ddsd.dwSize = sizeof(ddsd);
87     ddsd.dwFlags = DDSD_CAPS;
88     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
89     ddsd.dwBackBufferCount = 1;
90     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &Surface, NULL);
91     ok(hr==DD_OK, "CreateSurface returned: %08x\n", hr);
92     if(!Surface) 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     ok(hr == D3D_OK, "IDirect3D7_CreateDevice failed with %08x\n", hr);
106     if(!Direct3DDevice) goto err;
107     return TRUE;
108
109     err:
110     if(DirectDraw) IDirectDraw7_Release(DirectDraw);
111     if(Surface) IDirectDrawSurface7_Release(Surface);
112     if(Direct3D) IDirect3D7_Release(Direct3D);
113     if(Direct3DDevice) IDirect3DDevice7_Release(Direct3DDevice);
114     if(window) DestroyWindow(window);
115     return FALSE;
116 }
117
118 static void releaseObjects(void)
119 {
120     IDirect3DDevice7_Release(Direct3DDevice);
121     IDirect3D7_Release(Direct3D);
122     IDirectDrawSurface7_Release(Surface);
123     IDirectDraw7_Release(DirectDraw);
124     DestroyWindow(window);
125 }
126
127 static DWORD getPixelColor(IDirect3DDevice7 *device, UINT x, UINT y)
128 {
129     DWORD ret;
130     HRESULT hr;
131     DDSURFACEDESC2 ddsd;
132     RECT rectToLock = {x, y, x+1, y+1};
133     IDirectDrawSurface7 *surf = NULL;
134
135     /* Some implementations seem to dislike direct locking on the front buffer. Thus copy the front buffer
136      * to an offscreen surface and lock it instead of the front buffer
137      */
138     memset(&ddsd, 0, sizeof(ddsd));
139     ddsd.dwSize = sizeof(ddsd);
140     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
141     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
142     ddsd.dwWidth = 640;
143     ddsd.dwHeight = 480;
144     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
145     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &surf, NULL);
146     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed with %08x\n", hr);
147     if(!surf)
148     {
149         trace("cannot create helper surface\n");
150         return 0xdeadbeef;
151     }
152
153     memset(&ddsd, 0, sizeof(ddsd));
154     ddsd.dwSize = sizeof(ddsd);
155     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
156
157     hr = IDirectDrawSurface_BltFast(surf, 0, 0, Surface, NULL, 0);
158     ok(hr == DD_OK, "IDirectDrawSurface7_BltFast returned %08x\n", hr);
159     if(FAILED(hr))
160     {
161         trace("Cannot blit\n");
162         ret = 0xdeadbee;
163         goto out;
164     }
165
166     hr = IDirectDrawSurface7_Lock(surf, &rectToLock, &ddsd, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
167     if(FAILED(hr))
168     {
169         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
170         ret = 0xdeadbeec;
171         goto out;
172     }
173
174     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
175      * really important for these tests
176      */
177     ret = ((DWORD *) ddsd.lpSurface)[0] & 0x00ffffff;
178     hr = IDirectDrawSurface7_Unlock(surf, &rectToLock);
179     if(FAILED(hr))
180     {
181         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
182     }
183
184 out:
185     IDirectDrawSurface7_Release(surf);
186     return ret;
187 }
188
189 struct vertex
190 {
191     float x, y, z;
192     DWORD diffuse;
193 };
194
195 struct nvertex
196 {
197     float x, y, z;
198     float nx, ny, nz;
199     DWORD diffuse;
200 };
201
202 static void lighting_test(IDirect3DDevice7 *device)
203 {
204     HRESULT hr;
205     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
206     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
207     DWORD color;
208
209     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
210                       0.0f, 1.0f, 0.0f, 0.0f,
211                       0.0f, 0.0f, 1.0f, 0.0f,
212                       0.0f, 0.0f, 0.0f, 1.0f };
213
214     struct vertex unlitquad[] =
215     {
216         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
217         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
218         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
219         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
220     };
221     struct vertex litquad[] =
222     {
223         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
224         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
225         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
226         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
227     };
228     struct nvertex unlitnquad[] =
229     {
230         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
231         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
232         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
233         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
234     };
235     struct nvertex litnquad[] =
236     {
237         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
238         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
239         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
240         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
241     };
242     WORD Indices[] = {0, 1, 2, 2, 3, 0};
243
244     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
245     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
246
247     /* Setup some states that may cause issues */
248     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, (D3DMATRIX *) mat);
249     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
250     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, (D3DMATRIX *)mat);
251     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
252     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, (D3DMATRIX *) mat);
253     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
254     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
255     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
256     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
257     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
258     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
259     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
260     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
261     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
262     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
263     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
264     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
265     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
266     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
267     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed with %08x\n", hr);
268
269     hr = IDirect3DDevice7_BeginScene(device);
270     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
271     if(hr == D3D_OK)
272     {
273         /* No lights are defined... That means, lit vertices should be entirely black */
274         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
275         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
276         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4 /* NumVerts */,
277                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
278         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
279
280         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
281         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
282         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4 /* NumVerts */,
283                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
284         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
285
286         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
287         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
288         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4 /* NumVerts */,
289                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
290         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
291
292         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
293         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
294         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4 /* NumVerts */,
295                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
296         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
297
298         IDirect3DDevice7_EndScene(device);
299         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
300     }
301
302     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
303     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
304     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
305     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
306     color = getPixelColor(device, 480, 360); /* lower left quad - unlit width normals */
307     ok(color == 0x000000ff, "Unlit quad width normals has color %08x\n", color);
308     color = getPixelColor(device, 480, 120); /* upper left quad - lit width normals */
309     ok(color == 0x00000000, "Lit quad width normals has color %08x\n", color);
310
311     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
312     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
313 }
314
315 static void clear_test(IDirect3DDevice7 *device)
316 {
317     /* Tests the correctness of clearing parameters */
318     HRESULT hr;
319     D3DRECT rect[2];
320     D3DRECT rect_negneg;
321     DWORD color;
322
323     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
324     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
325
326     /* Positive x, negative y */
327     U1(rect[0]).x1 = 0;
328     U2(rect[0]).y1 = 480;
329     U3(rect[0]).x2 = 320;
330     U4(rect[0]).y2 = 240;
331
332     /* Positive x, positive y */
333     U1(rect[1]).x1 = 0;
334     U2(rect[1]).y1 = 0;
335     U3(rect[1]).x2 = 320;
336     U4(rect[1]).y2 = 240;
337     /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
338      * is ignored, the positive is still cleared afterwards
339      */
340     hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
341     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
342
343     /* negative x, negative y */
344     U1(rect_negneg).x1 = 640;
345     U2(rect_negneg).y1 = 240;
346     U3(rect_negneg).x2 = 320;
347     U4(rect_negneg).y2 = 0;
348     hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
349     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
350
351     color = getPixelColor(device, 160, 360); /* lower left quad */
352     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
353     color = getPixelColor(device, 160, 120); /* upper left quad */
354     ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
355     color = getPixelColor(device, 480, 360); /* lower right quad  */
356     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
357     color = getPixelColor(device, 480, 120); /* upper right quad */
358     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
359 }
360
361 struct sVertex {
362     float x, y, z;
363     DWORD diffuse;
364     DWORD specular;
365 };
366
367 struct sVertexT {
368     float x, y, z, rhw;
369     DWORD diffuse;
370     DWORD specular;
371 };
372
373 static void fog_test(IDirect3DDevice7 *device)
374 {
375     HRESULT hr;
376     DWORD color;
377     float start = 0.0, end = 1.0;
378     D3DDEVICEDESC7 caps;
379
380     /* Gets full z based fog with linear fog, no fog with specular color */
381     struct sVertex unstransformed_1[] = {
382         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
383         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
384         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
385         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
386     };
387     /* Ok, I am too lazy to deal with transform matrices */
388     struct sVertex unstransformed_2[] = {
389         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
390         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
391         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
392         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
393     };
394     /* Untransformed ones. Give them a different diffuse color to make the test look
395      * nicer. It also makes making sure that they are drawn correctly easier.
396      */
397     struct sVertexT transformed_1[] = {
398         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
399         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
400         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
401         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
402     };
403     struct sVertexT transformed_2[] = {
404         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
405         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
406         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
407         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
408     };
409     WORD Indices[] = {0, 1, 2, 2, 3, 0};
410
411     memset(&caps, 0, sizeof(caps));
412     hr = IDirect3DDevice7_GetCaps(device, &caps);
413     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
414     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
415     ok(hr == D3D_OK, "IDirect3DDevice7_Clear returned %08x\n", hr);
416
417     /* Setup initial states: No lighting, fog on, fog color */
418     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
419     ok(hr == D3D_OK, "Turning off lighting returned %08x\n", hr);
420     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
421     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
422     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xFF00FF00 /* A nice green */);
423     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
424
425     /* First test: Both table fog and vertex fog off */
426     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
427     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
428     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE);
429     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
430
431     /* Start = 0, end = 1. Should be default, but set them */
432     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, *((DWORD *) &start));
433     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
434     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, *((DWORD *) &end));
435     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
436
437     if(IDirect3DDevice7_BeginScene(device) == D3D_OK)
438     {
439         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
440         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
441                                                    unstransformed_1, 4, Indices, 6, 0);
442         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
443
444         /* That makes it use the Z value */
445         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
446         ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
447         /* Untransformed, vertex fog != none (or table fog != none):
448          * Use the Z value as input into the equation
449          */
450         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
451                                                    unstransformed_2, 4, Indices, 6, 0);
452         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
453
454         /* transformed verts */
455         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
456         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
457         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
458                                                    transformed_1, 4, Indices, 6, 0);
459         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
460
461         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
462         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
463         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
464          * equation
465          */
466         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
467                                                    transformed_2, 4, Indices, 6, 0);
468         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
469
470         hr = IDirect3DDevice7_EndScene(device);
471         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
472     }
473     else
474     {
475         ok(FALSE, "BeginScene failed\n");
476     }
477
478     color = getPixelColor(device, 160, 360);
479     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
480     color = getPixelColor(device, 160, 120);
481     ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
482     color = getPixelColor(device, 480, 120);
483     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
484     if(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE)
485     {
486         color = getPixelColor(device, 480, 360);
487         ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
488     }
489     else
490     {
491         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
492          * The settings above result in no fogging with vertex fog
493          */
494         color = getPixelColor(device, 480, 120);
495         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
496         trace("Info: Table fog not supported by this device\n");
497     }
498
499     /* Turn off the fog master switch to avoid confusing other tests */
500     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
501     ok(hr == D3D_OK, "Turning off fog calculations returned %08x\n", hr);
502 }
503
504 static void offscreen_test(IDirect3DDevice7 *device)
505 {
506     HRESULT hr;
507     IDirectDrawSurface7 *backbuffer = NULL, *offscreen = NULL;
508     DWORD color;
509     DDSURFACEDESC2 ddsd;
510
511     static const float quad[][5] = {
512         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
513         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
514         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
515         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
516     };
517
518     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
519     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
520
521     memset(&ddsd, 0, sizeof(ddsd));
522     ddsd.dwSize = sizeof(ddsd);
523     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
524     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
525     ddsd.dwWidth = 128;
526     ddsd.dwHeight = 128;
527     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
528     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &offscreen, NULL);
529     ok(hr == D3D_OK, "Creating the offscreen render target failed, hr = %08x\n", hr);
530     if(!offscreen) {
531         goto out;
532     }
533
534     hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
535     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
536     if(!backbuffer) {
537         goto out;
538     }
539
540     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
541     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
542     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
543     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
544     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DFILTER_NEAREST);
545     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
546     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DFILTER_NEAREST);
547     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
548     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
549     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned hr = %08x\n", hr);
550
551     if(IDirect3DDevice7_BeginScene(device) == D3D_OK) {
552         hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
553         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
554         hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
555         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
556
557         /* Draw without textures - Should resut in a white quad */
558         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
559         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
560
561         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
562         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
563         hr = IDirect3DDevice7_SetTexture(device, 0, offscreen);
564         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
565
566         /* This time with the texture */
567         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
568         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
569
570         IDirect3DDevice7_EndScene(device);
571     }
572
573     /* Center quad - should be white */
574     color = getPixelColor(device, 320, 240);
575     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
576     /* Some quad in the cleared part of the texture */
577     color = getPixelColor(device, 170, 240);
578     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
579     /* Part of the originally cleared back buffer */
580     color = getPixelColor(device, 10, 10);
581     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
582     if(0) {
583         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
584          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
585          * the offscreen rendering mode this test would succeed or fail
586          */
587         color = getPixelColor(device, 10, 470);
588         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
589     }
590
591 out:
592     hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
593
594     /* restore things */
595     if(backbuffer) {
596         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
597         IDirectDrawSurface7_Release(backbuffer);
598     }
599     if(offscreen) {
600         IDirectDrawSurface7_Release(offscreen);
601     }
602 }
603
604 static void alpha_test(IDirect3DDevice7 *device)
605 {
606     HRESULT hr;
607     IDirectDrawSurface7 *backbuffer = NULL, *offscreen = NULL;
608     DWORD color, red, green, blue;
609     DDSURFACEDESC2 ddsd;
610
611     struct vertex quad1[] =
612     {
613         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
614         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
615         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
616         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
617     };
618     struct vertex quad2[] =
619     {
620         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
621         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
622         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
623         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
624     };
625     static const float composite_quad[][5] = {
626         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
627         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
628         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
629         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
630     };
631
632     /* Clear the render target with alpha = 0.5 */
633     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
634     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
635
636     memset(&ddsd, 0, sizeof(ddsd));
637     ddsd.dwSize = sizeof(ddsd);
638     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
639     ddsd.dwWidth = 128;
640     ddsd.dwHeight = 128;
641     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
642     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
643     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount      = 32;
644     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
645     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
646     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask         = 0x000000ff;
647     U5(U4(ddsd).ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
648     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &offscreen, NULL);
649     ok(hr == D3D_OK, "Creating the offscreen render target failed, hr = %08x\n", hr);
650     if(!offscreen) {
651         goto out;
652     }
653     hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
654     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
655     if(!backbuffer) {
656         goto out;
657     }
658
659     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
660     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
661     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
662     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
663     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DFILTER_NEAREST);
664     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
665     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DFILTER_NEAREST);
666     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
667
668     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
669     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
670     if(IDirect3DDevice7_BeginScene(device) == D3D_OK) {
671
672         /* Draw two quads, one with src alpha blending, one with dest alpha blending. The
673          * SRCALPHA / INVSRCALPHA blend doesn't give any surprises. Colors are blended based on
674          * the input alpha
675          *
676          * The DESTALPHA / INVDESTALPHA do not "work" on the regular buffer because there is no alpha.
677          * They give essentially ZERO and ONE blend factors
678          */
679         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
680         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
681         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
682         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
683         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad1, 4, 0);
684         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
685
686         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTALPHA);
687         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
688         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVDESTALPHA);
689         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
690         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad2, 4, 0);
691         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
692
693         /* Switch to the offscreen buffer, and redo the testing. SRCALPHA and DESTALPHA. The offscreen buffer
694          * has a alpha channel on its own. Clear the offscreen buffer with alpha = 0.5 again, then draw the
695          * quads again. The SRCALPHA/INVSRCALPHA doesn't give any surprises, but the DESTALPHA/INVDESTALPHA
696          * blending works as supposed now - blend factor is 0.5 in both cases, not 0.75 as from the input
697          * vertices
698          */
699         hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
700         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
701         hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
702         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
703
704         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
705         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
706         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
707         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
708         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad1, 4, 0);
709         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
710
711         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTALPHA);
712         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
713         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVDESTALPHA);
714         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
715         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad2, 4, 0);
716         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
717
718         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
719         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
720
721         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
722          * Disable alpha blending for the final composition
723          */
724         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
725         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
726
727         hr = IDirect3DDevice7_SetTexture(device, 0, offscreen);
728         ok(hr == D3D_OK, "IDirect3DDevice7_SetTexture failed, hr = %08x\n", hr);
729         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, composite_quad, 4, 0);
730         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
731         hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
732         ok(hr == D3D_OK, "IDirect3DDevice7_SetTexture failed, hr = %08x\n", hr);
733
734         hr = IDirect3DDevice7_EndScene(device);
735         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
736     }
737
738     color = getPixelColor(device, 160, 360);
739     red =   (color & 0x00ff0000) >> 16;
740     green = (color & 0x0000ff00) >>  8;
741     blue =  (color & 0x000000ff);
742     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
743        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
744
745     color = getPixelColor(device, 160, 120);
746     red =   (color & 0x00ff0000) >> 16;
747     green = (color & 0x0000ff00) >>  8;
748     blue =  (color & 0x000000ff);
749     ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff ,
750        "DSTALPHA on frame buffer returned color %08x, expected 0x00ff0000\n", color);
751
752     color = getPixelColor(device, 480, 360);
753     red =   (color & 0x00ff0000) >> 16;
754     green = (color & 0x0000ff00) >>  8;
755     blue =  (color & 0x000000ff);
756     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
757        "SRCALPHA on texture returned color %08x, expected bar\n", color);
758
759     color = getPixelColor(device, 480, 120);
760     red =   (color & 0x00ff0000) >> 16;
761     green = (color & 0x0000ff00) >>  8;
762     blue =  (color & 0x000000ff);
763     ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81,
764        "DSTALPHA on texture returned color %08x, expected foo\n", color);
765
766     out:
767     if(offscreen) IDirectDrawSurface7_Release(offscreen);
768     if(backbuffer) IDirectDrawSurface7_Release(backbuffer);
769 }
770
771 static void rhw_zero_test(IDirect3DDevice7 *device)
772 {
773 /* Test if it will render a quad correctly when vertex rhw = 0 */
774     HRESULT hr;
775     DWORD color;
776
777     struct {
778         float x, y, z;
779         float rhw;
780         DWORD diffuse;
781         } quad1[] =
782     {
783         {0, 100, 0, 0, 0xffffffff},
784         {0, 0, 0, 0, 0xffffffff},
785         {100, 100, 0, 0, 0xffffffff},
786         {100, 0, 0, 0, 0xffffffff},
787     };
788
789     /* Clear to black */
790     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0, 0);
791     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
792
793     hr = IDirect3DDevice7_BeginScene(device);
794     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
795
796     if (SUCCEEDED(hr)) {
797         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad1, 4, 0);
798         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
799
800         hr = IDirect3DDevice7_EndScene(device);
801         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
802     }
803
804     color = getPixelColor(device, 5, 5);
805     ok(color == 0xffffff, "Got color %08x, expected 00ffffff\n", color);
806
807     color = getPixelColor(device, 105, 105);
808     ok(color == 0, "Got color %08x, expected 00000000\n", color);
809 }
810
811 static BOOL D3D1_createObjects(void)
812 {
813     WNDCLASS wc = {0};
814     HRESULT hr;
815     DDSURFACEDESC ddsd;
816     D3DEXECUTEBUFFERDESC exdesc;
817     D3DVIEWPORT vp_data;
818
819     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
820     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
821
822     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
823     if (FAILED(hr)) {
824         return FALSE;
825     }
826
827     wc.lpfnWndProc = &DefWindowProc;
828     wc.lpszClassName = "texturemapblend_test_wc";
829     RegisterClass(&wc);
830     window = CreateWindow("texturemapblend_test_wc", "texturemapblend_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
831
832     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
833     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
834     if(FAILED(hr)) {
835         return FALSE;
836     }
837
838     hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 32);
839     if(FAILED(hr)) {
840         /* 24 bit is fine too */
841         hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 24);
842     }
843     ok(hr==DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode returned: %x\n", hr);
844     if (FAILED(hr)) {
845         return FALSE;
846     }
847
848     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
849     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
850     if (FAILED(hr)) {
851         return FALSE;
852     }
853
854     memset(&ddsd, 0, sizeof(ddsd));
855     ddsd.dwSize = sizeof(ddsd);
856     ddsd.dwFlags = DDSD_CAPS;
857     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
858     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
859     ok(hr==DD_OK, "CreateSurface returned: %x\n", hr);
860     if (FAILED(hr)) {
861         return FALSE;
862     }
863
864     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **) &Direct3DDevice1);
865     if(FAILED(hr)) {
866         trace("Creating a HAL device failed, trying Ref\n");
867         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRefDevice, (void **) &Direct3DDevice1);
868     }
869     ok(hr==D3D_OK, "Creating 3D device returned: %x\n", hr);
870     if(FAILED(hr)) {
871         return FALSE;
872     }
873
874     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
875     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
876     if (FAILED(hr)) {
877         return FALSE;
878     }
879
880     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
881     ok(hr == D3D_OK || hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
882     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
883     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
884     vp_data.dwSize = sizeof(vp_data);
885     vp_data.dwX = 0;
886     vp_data.dwY = 0;
887     vp_data.dwWidth = 640;
888     vp_data.dwHeight = 480;
889     vp_data.dvScaleX = 1;
890     vp_data.dvScaleY = 1;
891     vp_data.dvMaxX = 640;
892     vp_data.dvMaxY = 480;
893     vp_data.dvMinZ = 0;
894     vp_data.dvMaxZ = 1;
895     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
896     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
897
898     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
899     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
900     exdesc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
901     exdesc.dwBufferSize = 512;
902     exdesc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
903     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &exdesc, &ExecuteBuffer, NULL);
904     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed with %08x\n", hr);
905     if (FAILED(hr)) {
906         return FALSE;
907     }
908
909     return TRUE;
910 }
911
912 static void D3D1_releaseObjects(void)
913 {
914     if(ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
915     if(Surface1) IDirectDrawSurface_Release(Surface1);
916     if(Viewport) IDirect3DViewport_Release(Viewport);
917     if(Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
918     if(Direct3D1) IDirect3D_Release(Direct3D1);
919     if(DirectDraw1) IDirectDraw_Release(DirectDraw1);
920     if(window) DestroyWindow(window);
921 }
922
923 static DWORD D3D1_getPixelColor(IDirectDraw *DirectDraw1, IDirectDrawSurface *Surface, UINT x, UINT y)
924 {
925     DWORD ret;
926     HRESULT hr;
927     DDSURFACEDESC ddsd;
928     RECT rectToLock = {x, y, x+1, y+1};
929     IDirectDrawSurface *surf = NULL;
930
931     /* Some implementations seem to dislike direct locking on the front buffer. Thus copy the front buffer
932      * to an offscreen surface and lock it instead of the front buffer
933      */
934     memset(&ddsd, 0, sizeof(ddsd));
935     ddsd.dwSize = sizeof(ddsd);
936     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
937     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
938     ddsd.dwWidth = 640;
939     ddsd.dwHeight = 480;
940     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
941     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
942     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed with %08x\n", hr);
943     if(!surf)
944     {
945         trace("cannot create helper surface\n");
946         return 0xdeadbeef;
947     }
948
949     memset(&ddsd, 0, sizeof(ddsd));
950     ddsd.dwSize = sizeof(ddsd);
951     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
952
953     hr = IDirectDrawSurface_BltFast(surf, 0, 0, Surface, NULL, 0);
954     ok(hr == DD_OK, "IDirectDrawSurface_BltFast returned %08x\n", hr);
955     if(FAILED(hr))
956     {
957         trace("Cannot blit\n");
958         ret = 0xdeadbee;
959         goto out;
960     }
961
962     hr = IDirectDrawSurface_Lock(surf, &rectToLock, &ddsd, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
963     if(FAILED(hr))
964     {
965         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
966         ret = 0xdeadbeec;
967         goto out;
968     }
969
970     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
971      * really important for these tests
972      */
973     ret = ((DWORD *) ddsd.lpSurface)[0] & 0x00ffffff;
974     hr = IDirectDrawSurface_Unlock(surf, &rectToLock);
975     if(FAILED(hr))
976     {
977         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
978     }
979
980 out:
981     IDirectDrawSurface_Release(surf);
982     return ret;
983 }
984
985 #define EXEBUF_START_RENDER_STATES(count, ptr) do {\
986                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_STATERENDER;\
987                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DSTATE);\
988                          ((D3DINSTRUCTION*)(ptr))->wCount = count;\
989                          ptr = ((D3DINSTRUCTION*)(ptr))+1; } while (0)
990
991 #define EXEBUF_PUT_RENDER_STATE(state, value, ptr) do {\
992                          ((D3DSTATE*)(ptr))->drstRenderStateType = state;\
993                          ((D3DSTATE*)(ptr))->dwArg[0] = value;\
994                          ptr = ((D3DSTATE*)(ptr))+1; } while (0)
995
996 #define EXEBUF_PUT_PROCESSVERTICES(nvertices, ptr) do {\
997                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_PROCESSVERTICES;\
998                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DPROCESSVERTICES);\
999                          ((D3DINSTRUCTION*)(ptr))->wCount = 1;\
1000                          ptr = ((D3DINSTRUCTION*)(ptr))+1;\
1001                          ((D3DPROCESSVERTICES*)(ptr))->dwFlags = D3DPROCESSVERTICES_COPY;\
1002                          ((D3DPROCESSVERTICES*)(ptr))->wStart = 0;\
1003                          ((D3DPROCESSVERTICES*)(ptr))->wDest = 0;\
1004                          ((D3DPROCESSVERTICES*)(ptr))->dwCount = nvertices;\
1005                          ((D3DPROCESSVERTICES*)(ptr))->dwReserved = 0;\
1006                          ptr = ((D3DPROCESSVERTICES*)(ptr))+1; } while (0)
1007
1008 #define EXEBUF_END(ptr) do {\
1009                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_EXIT;\
1010                          ((D3DINSTRUCTION*)(ptr))->bSize = 0;\
1011                          ((D3DINSTRUCTION*)(ptr))->wCount = 0;\
1012                          ptr = ((D3DINSTRUCTION*)(ptr))+1; } while (0)
1013
1014 #define EXEBUF_PUT_QUAD(base_idx, ptr) do {\
1015                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_TRIANGLE;\
1016                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DTRIANGLE);\
1017                          ((D3DINSTRUCTION*)(ptr))->wCount = 2;\
1018                          ptr = ((D3DINSTRUCTION*)(ptr))+1;\
1019                          ((D3DTRIANGLE*)(ptr))->v1 = base_idx;\
1020                          ((D3DTRIANGLE*)(ptr))->v2 = (base_idx) + 1;\
1021                          ((D3DTRIANGLE*)(ptr))->v3 = (base_idx) + 3;\
1022                          ((D3DTRIANGLE*)(ptr))->wFlags = 0;\
1023                          ptr = ((D3DTRIANGLE*)ptr)+1;\
1024                          ((D3DTRIANGLE*)(ptr))->v1 = (base_idx) + 1;\
1025                          ((D3DTRIANGLE*)(ptr))->v2 = (base_idx) + 2;\
1026                          ((D3DTRIANGLE*)(ptr))->v3 = (base_idx) + 3;\
1027                          ((D3DTRIANGLE*)(ptr))->wFlags = 0;\
1028                          ptr = ((D3DTRIANGLE*)(ptr))+1;\
1029                         } while (0)
1030
1031 static void D3D1_TextureMapBlendTest(void)
1032 {
1033     HRESULT hr;
1034     DDSURFACEDESC ddsd;
1035     D3DEXECUTEBUFFERDESC exdesc;
1036     D3DEXECUTEDATA exdata;
1037     DDBLTFX ddbltfx;
1038     RECT rect = { 0, 0, 64, 128 };
1039     DWORD color, red, blue, green;
1040     void *exe_buffer_ptr;
1041     DWORD exe_length;
1042     D3DTEXTUREHANDLE htex;
1043     DDCOLORKEY clrKey;
1044     IDirectDrawSurface *TexSurface = NULL;
1045     IDirect3DTexture *Texture = NULL;
1046
1047     struct {
1048         float x, y, z;
1049         float rhw;
1050         DWORD diffuse;
1051         DWORD specular;
1052         float tu, tv;
1053         } test1_quads[] =
1054     {
1055           {0.0f,   0.0f,     0.0f, 1.0f, 0xffffffff, 0, 0.0f, 0.0f},
1056           {640.0f, 0.0f,     0.0f, 1.0f, 0xffffffff, 0, 1.0f, 0.0f},
1057           {640.0f, 240.0f,   0.0f, 1.0f, 0xffffffff, 0, 1.0f, 1.0f},
1058           {0.0f,   240.0f,   0.0f, 1.0f, 0xffffffff, 0, 0.0f, 1.0f},
1059           {0.0f,   240.0f,   0.0f, 1.0f, 0x80ffffff, 0, 0.0f, 0.0f},
1060           {640.0f, 240.0f,   0.0f, 1.0f, 0x80ffffff, 0, 1.0f, 0.0f},
1061           {640.0f, 480.0f,   0.0f, 1.0f, 0x80ffffff, 0, 1.0f, 1.0f},
1062           {0.0f,   480.0f,   0.0f, 1.0f, 0x80ffffff, 0, 0.0f, 1.0f}
1063     },  test2_quads[] =
1064           {
1065           {0.0f,   0.0f,     0.0f, 1.0f, 0x00ff0080, 0, 0.0f, 0.0f},
1066           {640.0f, 0.0f,     0.0f, 1.0f, 0x00ff0080, 0, 1.0f, 0.0f},
1067           {640.0f, 240.0f,   0.0f, 1.0f, 0x00ff0080, 0, 1.0f, 1.0f},
1068           {0.0f,   240.0f,   0.0f, 1.0f, 0x00ff0080, 0, 0.0f, 1.0f},
1069           {0.0f,   240.0f,   0.0f, 1.0f, 0x008000ff, 0, 0.0f, 0.0f},
1070           {640.0f, 240.0f,   0.0f, 1.0f, 0x008000ff, 0, 1.0f, 0.0f},
1071           {640.0f, 480.0f,   0.0f, 1.0f, 0x008000ff, 0, 1.0f, 1.0f},
1072           {0.0f,   480.0f,   0.0f, 1.0f, 0x008000ff, 0, 0.0f, 1.0f}
1073     };
1074
1075     /* 1) Test alpha with DDPF_ALPHAPIXELS texture - should be be taken from texture alpha channel*/
1076     memset (&ddsd, 0, sizeof (ddsd));
1077     ddsd.dwSize = sizeof (ddsd);
1078     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1079     ddsd.dwHeight = 128;
1080     ddsd.dwWidth = 128;
1081     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1082     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1083     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1084     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1085     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1086     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1087     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1088     U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
1089     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1090     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1091     if (FAILED(hr)) {
1092         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1093         goto out;
1094     }
1095
1096     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1097                 (void *)&Texture);
1098     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1099     if (FAILED(hr)) {
1100         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1101         goto out;
1102     }
1103
1104     memset(&ddbltfx, 0, sizeof(ddbltfx));
1105     ddbltfx.dwSize = sizeof(ddbltfx);
1106     ddbltfx.dwFillColor = 0;
1107     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1108     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1109
1110     ddbltfx.dwFillColor = 0xff0000ff;
1111     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1112     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1113     ddbltfx.dwFillColor = 0x800000ff;
1114     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1115     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1116
1117     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1118     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1119     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1120     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1121     if (FAILED(hr)) {
1122         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1123         goto out;
1124     }
1125
1126     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1127
1128     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1129
1130     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1131
1132     EXEBUF_START_RENDER_STATES(12, exe_buffer_ptr);
1133     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_CULLMODE,         D3DCULL_NONE,              exe_buffer_ptr);
1134     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ZENABLE,          FALSE,                     exe_buffer_ptr);
1135     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_FOGENABLE,        FALSE,                     exe_buffer_ptr);
1136     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_SPECULARENABLE,   FALSE,                     exe_buffer_ptr);
1137     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMAG,       D3DFILTER_NEAREST,         exe_buffer_ptr);
1138     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMIN,       D3DFILTER_NEAREST,         exe_buffer_ptr);
1139     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_FILLMODE  ,       D3DFILL_SOLID,             exe_buffer_ptr);
1140     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_SRCBLEND,         D3DBLEND_SRCALPHA,         exe_buffer_ptr);
1141     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_DESTBLEND,        D3DBLEND_INVSRCALPHA,      exe_buffer_ptr);
1142     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE,                      exe_buffer_ptr);
1143     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMAPBLEND,  D3DTBLEND_MODULATE,        exe_buffer_ptr);
1144     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1145     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1146     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1147
1148     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1149     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1150
1151     EXEBUF_END(exe_buffer_ptr);
1152
1153     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1154
1155     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1156     if (FAILED(hr)) {
1157         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1158     }
1159
1160     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1161     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1162     exdata.dwVertexCount = 8;
1163     exdata.dwInstructionOffset = 256;
1164     exdata.dwInstructionLength = exe_length;
1165     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1166     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1167
1168     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1169     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1170
1171     if (SUCCEEDED(hr)) {
1172         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1173         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1174         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1175         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1176     }
1177
1178     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1179     red =   (color & 0x00ff0000) >> 16;
1180     green = (color & 0x0000ff00) >>  8;
1181     blue =  (color & 0x000000ff);
1182     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1183
1184     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1185     red =   (color & 0x00ff0000) >> 16;
1186     green = (color & 0x0000ff00) >>  8;
1187     blue =  (color & 0x000000ff);
1188     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1189
1190     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1191     red =   (color & 0x00ff0000) >> 16;
1192     green = (color & 0x0000ff00) >>  8;
1193     blue =  (color & 0x000000ff);
1194     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1195
1196     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1197     red =   (color & 0x00ff0000) >> 16;
1198     green = (color & 0x0000ff00) >>  8;
1199     blue =  (color & 0x000000ff);
1200     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1201
1202     /* 2) Test alpha with texture that has no alpha channel - alpha should be be taken from diffuse color */
1203     if(Texture) IDirect3DTexture_Release(Texture);
1204     Texture = NULL;
1205     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1206     TexSurface = NULL;
1207
1208     memset (&ddsd, 0, sizeof (ddsd));
1209     ddsd.dwSize = sizeof (ddsd);
1210     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1211     ddsd.dwHeight = 128;
1212     ddsd.dwWidth = 128;
1213     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1214     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1215     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
1216     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1217     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1218     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1219     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1220
1221     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1222     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1223     if (FAILED(hr)) {
1224         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1225         goto out;
1226     }
1227
1228     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1229                 (void *)&Texture);
1230     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1231     if (FAILED(hr)) {
1232         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1233         goto out;
1234     }
1235
1236     memset(&ddbltfx, 0, sizeof(ddbltfx));
1237     ddbltfx.dwSize = sizeof(ddbltfx);
1238     ddbltfx.dwFillColor = 0;
1239     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1240     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1241
1242     ddbltfx.dwFillColor = 0xff0000ff;
1243     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1244     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1245     ddbltfx.dwFillColor = 0x800000ff;
1246     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1247     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1248
1249     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1250     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1251     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1252     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1253     if (FAILED(hr)) {
1254         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1255         goto out;
1256     }
1257
1258     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1259
1260     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1261
1262     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1263
1264     EXEBUF_START_RENDER_STATES(1, exe_buffer_ptr);
1265     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1266     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1267     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1268
1269     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1270     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1271
1272     EXEBUF_END(exe_buffer_ptr);
1273
1274     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1275
1276     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1277     if (FAILED(hr)) {
1278         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1279     }
1280
1281     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1282     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1283     exdata.dwVertexCount = 8;
1284     exdata.dwInstructionOffset = 256;
1285     exdata.dwInstructionLength = exe_length;
1286     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1287     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1288
1289     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1290     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1291
1292     if (SUCCEEDED(hr)) {
1293         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1294         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1295         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1296         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1297     }
1298
1299     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1300     red =   (color & 0x00ff0000) >> 16;
1301     green = (color & 0x0000ff00) >>  8;
1302     blue =  (color & 0x000000ff);
1303     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1304
1305     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1306     red =   (color & 0x00ff0000) >> 16;
1307     green = (color & 0x0000ff00) >>  8;
1308     blue =  (color & 0x000000ff);
1309     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1310
1311     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1312     red =   (color & 0x00ff0000) >> 16;
1313     green = (color & 0x0000ff00) >>  8;
1314     blue =  (color & 0x000000ff);
1315     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1316
1317     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1318     red =   (color & 0x00ff0000) >> 16;
1319     green = (color & 0x0000ff00) >>  8;
1320     blue =  (color & 0x000000ff);
1321     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1322
1323     /* 3) Test RGB - should multiply color components from diffuse color and texture */
1324     if(Texture) IDirect3DTexture_Release(Texture);
1325     Texture = NULL;
1326     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1327     TexSurface = NULL;
1328
1329     memset (&ddsd, 0, sizeof (ddsd));
1330     ddsd.dwSize = sizeof (ddsd);
1331     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1332     ddsd.dwHeight = 128;
1333     ddsd.dwWidth = 128;
1334     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1335     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1336     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1337     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1338     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1339     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1340     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1341     U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
1342     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1343     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1344     if (FAILED(hr)) {
1345         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1346         goto out;
1347     }
1348
1349     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1350                 (void *)&Texture);
1351     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1352     if (FAILED(hr)) {
1353         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1354         goto out;
1355     }
1356
1357     memset(&ddbltfx, 0, sizeof(ddbltfx));
1358     ddbltfx.dwSize = sizeof(ddbltfx);
1359     ddbltfx.dwFillColor = 0;
1360     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1361     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1362
1363     ddbltfx.dwFillColor = 0x00ffffff;
1364     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1365     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1366     ddbltfx.dwFillColor = 0x00ffff80;
1367     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1368     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1369
1370     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1371     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1372     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1373     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1374     if (FAILED(hr)) {
1375         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1376         goto out;
1377     }
1378
1379     memcpy(exdesc.lpData, test2_quads, sizeof(test2_quads));
1380
1381     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1382
1383     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1384
1385     EXEBUF_START_RENDER_STATES(2, exe_buffer_ptr);
1386     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE, exe_buffer_ptr);
1387     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1388     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1389     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1390
1391     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1392     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1393
1394     EXEBUF_END(exe_buffer_ptr);
1395
1396     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1397
1398     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1399     if (FAILED(hr)) {
1400         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1401     }
1402
1403     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1404     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1405     exdata.dwVertexCount = 8;
1406     exdata.dwInstructionOffset = 256;
1407     exdata.dwInstructionLength = exe_length;
1408     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1409     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1410
1411     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1412     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1413
1414     if (SUCCEEDED(hr)) {
1415         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1416         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1417         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1418         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1419     }
1420
1421     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1422     red =   (color & 0x00ff0000) >> 16;
1423     green = (color & 0x0000ff00) >>  8;
1424     blue =  (color & 0x000000ff);
1425     ok(red == 0xff &&  green == 0 && blue >= 0x3e && blue <= 0x42, "Got color %08x, expected 00ff0040 or near\n", color);
1426
1427     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1428     red =   (color & 0x00ff0000) >> 16;
1429     green = (color & 0x0000ff00) >>  8;
1430     blue =  (color & 0x000000ff);
1431     ok(red == 0xff &&  green == 0 && blue == 0x80, "Got color %08x, expected 00ff0080 or near\n", color);
1432
1433     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1434     red =   (color & 0x00ff0000) >> 16;
1435     green = (color & 0x0000ff00) >>  8;
1436     blue =  (color & 0x000000ff);
1437     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0x80, "Got color %08x, expected 00800080 or near\n", color);
1438
1439     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1440     red =   (color & 0x00ff0000) >> 16;
1441     green = (color & 0x0000ff00) >>  8;
1442     blue =  (color & 0x000000ff);
1443     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0xff, "Got color %08x, expected 008000ff or near\n", color);
1444
1445     /* 4) Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere) */
1446     if(Texture) IDirect3DTexture_Release(Texture);
1447     Texture = NULL;
1448     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1449     TexSurface = NULL;
1450
1451     memset (&ddsd, 0, sizeof (ddsd));
1452     ddsd.dwSize = sizeof (ddsd);
1453     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1454     ddsd.dwHeight = 128;
1455     ddsd.dwWidth = 128;
1456     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1457     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1458     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
1459     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 16;
1460     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0xf800;
1461     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x07e0;
1462     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x001f;
1463
1464     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1465     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1466     if (FAILED(hr)) {
1467         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1468         goto out;
1469     }
1470
1471     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1472                 (void *)&Texture);
1473     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1474     if (FAILED(hr)) {
1475         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1476         goto out;
1477     }
1478
1479     memset(&ddbltfx, 0, sizeof(ddbltfx));
1480     ddbltfx.dwSize = sizeof(ddbltfx);
1481     ddbltfx.dwFillColor = 0;
1482     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1483     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1484     ddbltfx.dwFillColor = 0xf800;
1485     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1486     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1487     ddbltfx.dwFillColor = 0x001f;
1488     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1489     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1490
1491     clrKey.dwColorSpaceLowValue = 0x001f;
1492     clrKey.dwColorSpaceHighValue = 0x001f;
1493     hr = IDirectDrawSurface_SetColorKey(TexSurface, DDCKEY_SRCBLT, &clrKey);
1494     ok(hr==D3D_OK, "IDirectDrawSurfac_SetColorKey returned: %x\n", hr);
1495
1496     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1497     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1498     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1499     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1500     if (FAILED(hr)) {
1501         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1502         goto out;
1503     }
1504
1505     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1506
1507     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1508
1509     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1510
1511     EXEBUF_START_RENDER_STATES(2, exe_buffer_ptr);
1512     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE, exe_buffer_ptr);
1513     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1514     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1515     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1516
1517     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1518     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1519
1520     EXEBUF_END(exe_buffer_ptr);
1521
1522     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1523
1524     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1525     if (FAILED(hr)) {
1526         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1527     }
1528
1529     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1530     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1531     exdata.dwVertexCount = 8;
1532     exdata.dwInstructionOffset = 256;
1533     exdata.dwInstructionLength = exe_length;
1534     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1535     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1536
1537     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1538     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1539
1540     if (SUCCEEDED(hr)) {
1541         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1542         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1543         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1544         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1545     }
1546
1547     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1548     ok(color == 0, "Got color %08x, expected 00000000\n", color);
1549
1550     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1551     red =   (color & 0x00ff0000) >> 16;
1552     green = (color & 0x0000ff00) >>  8;
1553     blue =  (color & 0x000000ff);
1554     ok(red == 0xff &&  green == 0 && blue == 0, "Got color %08x, expected 00ff0000 or near\n", color);
1555
1556     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1557     red =   (color & 0x00ff0000) >> 16;
1558     green = (color & 0x0000ff00) >>  8;
1559     blue =  (color & 0x000000ff);
1560     ok(color == 0, "Got color %08x, expected 00000000\n", color);
1561
1562     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1563     red =   (color & 0x00ff0000) >> 16;
1564     green = (color & 0x0000ff00) >>  8;
1565     blue =  (color & 0x000000ff);
1566     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0, "Got color %08x, expected 00800000 or near\n", color);
1567
1568     out:
1569
1570     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1571     if (Texture) IDirect3DTexture_Release(Texture);
1572 }
1573
1574 START_TEST(visual)
1575 {
1576     HRESULT hr;
1577     DWORD color;
1578     if(!createObjects())
1579     {
1580         skip("Cannot initialize DirectDraw and Direct3D, skipping\n");
1581         return;
1582     }
1583
1584     /* Check for the reliability of the returned data */
1585     hr = IDirect3DDevice7_Clear(Direct3DDevice, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1586     if(FAILED(hr))
1587     {
1588         trace("Clear failed, can't assure correctness of the test results, skipping\n");
1589         goto cleanup;
1590     }
1591
1592     color = getPixelColor(Direct3DDevice, 1, 1);
1593     if(color !=0x00ff0000)
1594     {
1595         trace("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
1596         goto cleanup;
1597     }
1598
1599     hr = IDirect3DDevice7_Clear(Direct3DDevice, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
1600     if(FAILED(hr))
1601     {
1602         trace("Clear failed, can't assure correctness of the test results, skipping\n");
1603         goto cleanup;
1604     }
1605
1606     color = getPixelColor(Direct3DDevice, 639, 479);
1607     if(color != 0x0000ddee)
1608     {
1609         trace("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
1610         goto cleanup;
1611     }
1612
1613     /* Now run the tests */
1614     lighting_test(Direct3DDevice);
1615     clear_test(Direct3DDevice);
1616     fog_test(Direct3DDevice);
1617     offscreen_test(Direct3DDevice);
1618     alpha_test(Direct3DDevice);
1619     rhw_zero_test(Direct3DDevice);
1620
1621     releaseObjects(); /* release DX7 interfaces to test D3D1 */
1622
1623     if(!D3D1_createObjects()) {
1624         skip("Cannot initialize D3D1, skipping\n");
1625     }
1626     else {
1627         D3D1_TextureMapBlendTest();
1628     }
1629     D3D1_releaseObjects();
1630     return ;
1631
1632 cleanup:
1633     releaseObjects();
1634 }