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