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