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