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