- added RECT support to the texture upload code
[wine] / dlls / d3d8 / utils.c
1 /*
2  * D3D8 utils
3  *
4  * Copyright 2002-2003 Jason Edmeades
5  *                     Raphael Junqueira
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23
24 #include <math.h>
25
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "wingdi.h"
32 #include "wine/debug.h"
33
34 #include "d3d8_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37
38
39 #if 0
40 # define VTRACE(A) TRACE A
41 #else 
42 # define VTRACE(A) 
43 #endif
44
45 const char* debug_d3ddevicetype(D3DDEVTYPE devtype) {
46   switch (devtype) {
47 #define DEVTYPE_TO_STR(dev) case dev: return #dev
48     DEVTYPE_TO_STR(D3DDEVTYPE_HAL);
49     DEVTYPE_TO_STR(D3DDEVTYPE_REF);
50     DEVTYPE_TO_STR(D3DDEVTYPE_SW);    
51 #undef DEVTYPE_TO_STR
52   default:
53     FIXME("Unrecognized %u D3DDEVTYPE!\n", devtype);
54     return "unrecognized";
55   }
56 }
57
58 const char* debug_d3dusage(DWORD usage) {
59   switch (usage) {
60 #define D3DUSAGE_TO_STR(u) case u: return #u
61     D3DUSAGE_TO_STR(D3DUSAGE_RENDERTARGET);
62     D3DUSAGE_TO_STR(D3DUSAGE_DEPTHSTENCIL);
63     D3DUSAGE_TO_STR(D3DUSAGE_WRITEONLY);
64     D3DUSAGE_TO_STR(D3DUSAGE_SOFTWAREPROCESSING);
65     D3DUSAGE_TO_STR(D3DUSAGE_DONOTCLIP);
66     D3DUSAGE_TO_STR(D3DUSAGE_POINTS);
67     D3DUSAGE_TO_STR(D3DUSAGE_RTPATCHES);
68     D3DUSAGE_TO_STR(D3DUSAGE_NPATCHES);
69     D3DUSAGE_TO_STR(D3DUSAGE_DYNAMIC);
70 #undef D3DUSAGE_TO_STR
71   case 0: return "none";
72   default:
73     FIXME("Unrecognized %lu Usage!\n", usage);
74     return "unrecognized";
75   }
76 }
77
78 const char* debug_d3dformat(D3DFORMAT fmt) {
79   switch (fmt) {
80 #define FMT_TO_STR(fmt) case fmt: return #fmt
81     FMT_TO_STR(D3DFMT_UNKNOWN);
82     FMT_TO_STR(D3DFMT_R8G8B8);
83     FMT_TO_STR(D3DFMT_A8R8G8B8);
84     FMT_TO_STR(D3DFMT_X8R8G8B8);
85     FMT_TO_STR(D3DFMT_R5G6B5);
86     FMT_TO_STR(D3DFMT_X1R5G5B5);
87     FMT_TO_STR(D3DFMT_A1R5G5B5);
88     FMT_TO_STR(D3DFMT_A4R4G4B4);
89     FMT_TO_STR(D3DFMT_R3G3B2);
90     FMT_TO_STR(D3DFMT_A8);
91     FMT_TO_STR(D3DFMT_A8R3G3B2);
92     FMT_TO_STR(D3DFMT_X4R4G4B4);
93     FMT_TO_STR(D3DFMT_A8P8);
94     FMT_TO_STR(D3DFMT_P8);
95     FMT_TO_STR(D3DFMT_L8);
96     FMT_TO_STR(D3DFMT_A8L8);
97     FMT_TO_STR(D3DFMT_A4L4);
98     FMT_TO_STR(D3DFMT_V8U8);
99     FMT_TO_STR(D3DFMT_L6V5U5);
100     FMT_TO_STR(D3DFMT_X8L8V8U8);
101     FMT_TO_STR(D3DFMT_Q8W8V8U8);
102     FMT_TO_STR(D3DFMT_V16U16);
103     FMT_TO_STR(D3DFMT_W11V11U10);
104     FMT_TO_STR(D3DFMT_UYVY);
105     FMT_TO_STR(D3DFMT_YUY2);
106     FMT_TO_STR(D3DFMT_DXT1);
107     FMT_TO_STR(D3DFMT_DXT2);
108     FMT_TO_STR(D3DFMT_DXT3);
109     FMT_TO_STR(D3DFMT_DXT4);
110     FMT_TO_STR(D3DFMT_DXT5);
111     FMT_TO_STR(D3DFMT_D16_LOCKABLE);
112     FMT_TO_STR(D3DFMT_D32);
113     FMT_TO_STR(D3DFMT_D15S1);
114     FMT_TO_STR(D3DFMT_D24S8);
115     FMT_TO_STR(D3DFMT_D16);
116     FMT_TO_STR(D3DFMT_D24X8);
117     FMT_TO_STR(D3DFMT_D24X4S4);
118     FMT_TO_STR(D3DFMT_VERTEXDATA);
119     FMT_TO_STR(D3DFMT_INDEX16);
120     FMT_TO_STR(D3DFMT_INDEX32);
121 #undef FMT_TO_STR
122   default:
123     FIXME("Unrecognized %u D3DFORMAT!\n", fmt);
124     return "unrecognized";
125   }
126 }
127
128 const char* debug_d3dressourcetype(D3DRESOURCETYPE res) {
129   switch (res) {
130 #define RES_TO_STR(res) case res: return #res;
131     RES_TO_STR(D3DRTYPE_SURFACE);
132     RES_TO_STR(D3DRTYPE_VOLUME);
133     RES_TO_STR(D3DRTYPE_TEXTURE);
134     RES_TO_STR(D3DRTYPE_VOLUMETEXTURE);
135     RES_TO_STR(D3DRTYPE_CUBETEXTURE);
136     RES_TO_STR(D3DRTYPE_VERTEXBUFFER);
137     RES_TO_STR(D3DRTYPE_INDEXBUFFER);
138 #undef  RES_TO_STR
139   default:
140     FIXME("Unrecognized %u D3DRESOURCETYPE!\n", res);
141     return "unrecognized";
142   }
143 }
144
145 const char* debug_d3dprimitivetype(D3DPRIMITIVETYPE PrimitiveType) {
146   switch (PrimitiveType) {
147 #define PRIM_TO_STR(prim) case prim: return #prim;
148     PRIM_TO_STR(D3DPT_POINTLIST);
149     PRIM_TO_STR(D3DPT_LINELIST);
150     PRIM_TO_STR(D3DPT_LINESTRIP);
151     PRIM_TO_STR(D3DPT_TRIANGLELIST);
152     PRIM_TO_STR(D3DPT_TRIANGLESTRIP);
153     PRIM_TO_STR(D3DPT_TRIANGLEFAN);
154 #undef  PRIM_TO_STR
155   default:
156     FIXME("Unrecognized %u D3DPRIMITIVETYPE!\n", PrimitiveType);
157     return "unrecognized";
158   }
159 }
160
161 const char* debug_d3dpool(D3DPOOL Pool) {
162   switch (Pool) {
163 #define POOL_TO_STR(p) case p: return #p;
164     POOL_TO_STR(D3DPOOL_DEFAULT);
165     POOL_TO_STR(D3DPOOL_MANAGED);
166     POOL_TO_STR(D3DPOOL_SYSTEMMEM);
167     POOL_TO_STR(D3DPOOL_SCRATCH);
168 #undef  POOL_TO_STR
169   default:
170     FIXME("Unrecognized %u D3DPOOL!\n", Pool);
171     return "unrecognized";
172   }
173 }
174
175 /*
176  * Simple utility routines used for dx -> gl mapping of byte formats
177  */
178 int D3DPrimitiveListGetVertexSize(D3DPRIMITIVETYPE PrimitiveType, int iNumPrim) {
179   switch (PrimitiveType) {
180   case D3DPT_POINTLIST:     return iNumPrim;
181   case D3DPT_LINELIST:      return iNumPrim * 2;
182   case D3DPT_LINESTRIP:     return iNumPrim + 1;
183   case D3DPT_TRIANGLELIST:  return iNumPrim * 3;
184   case D3DPT_TRIANGLESTRIP: return iNumPrim + 2;
185   case D3DPT_TRIANGLEFAN:   return iNumPrim + 2;
186   default:
187     FIXME("Unrecognized %u D3DPRIMITIVETYPE!\n", PrimitiveType);
188     return 0;
189   }
190 }
191
192 int D3DPrimitive2GLenum(D3DPRIMITIVETYPE PrimitiveType) {
193   switch (PrimitiveType) {
194   case D3DPT_POINTLIST:     return GL_POINTS;
195   case D3DPT_LINELIST:      return GL_LINES;
196   case D3DPT_LINESTRIP:     return GL_LINE_STRIP;
197   case D3DPT_TRIANGLELIST:  return GL_TRIANGLES;
198   case D3DPT_TRIANGLESTRIP: return GL_TRIANGLE_STRIP;
199   case D3DPT_TRIANGLEFAN:   return GL_TRIANGLE_FAN;
200   default:
201     FIXME("Unrecognized %u D3DPRIMITIVETYPE!\n", PrimitiveType);
202     return GL_POLYGON;
203   }
204 }
205
206 int D3DFVFGetSize(D3DFORMAT fvf) {
207   int ret = 0;
208   if      (fvf & D3DFVF_XYZ)    ret += 3 * sizeof(float);
209   else if (fvf & D3DFVF_XYZRHW) ret += 4 * sizeof(float);
210   if (fvf & D3DFVF_NORMAL)      ret += 3 * sizeof(float);
211   if (fvf & D3DFVF_PSIZE)       ret += sizeof(float);
212   if (fvf & D3DFVF_DIFFUSE)     ret += sizeof(DWORD);
213   if (fvf & D3DFVF_SPECULAR)    ret += sizeof(DWORD);
214   /*if (fvf & D3DFVF_TEX1)        ret += 1;*/
215   return ret;
216 }
217
218 GLenum D3DFmt2GLDepthFmt(D3DFORMAT fmt) {
219   switch (fmt) {
220   /* depth/stencil buffer */
221   case D3DFMT_D16_LOCKABLE:
222   case D3DFMT_D16:
223   case D3DFMT_D15S1:
224   case D3DFMT_D24X4S4:
225   case D3DFMT_D24S8:
226   case D3DFMT_D24X8:
227   case D3DFMT_D32:
228     return GL_DEPTH_COMPONENT;
229   default:
230     FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
231   }
232   return 0;
233 }
234
235 GLenum D3DFmt2GLDepthType(D3DFORMAT fmt) {
236   switch (fmt) {
237   /* depth/stencil buffer */
238   case D3DFMT_D15S1:
239   case D3DFMT_D16_LOCKABLE:     
240   case D3DFMT_D16:              
241     return GL_UNSIGNED_SHORT;
242   case D3DFMT_D24X4S4:          
243   case D3DFMT_D24S8:            
244   case D3DFMT_D24X8:            
245   case D3DFMT_D32:              
246     return GL_UNSIGNED_INT;
247   default:
248     FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
249   }
250   return 0;
251 }
252
253 SHORT D3DFmtGetBpp(IDirect3DDevice8Impl* This, D3DFORMAT fmt) {
254     SHORT retVal;
255
256     switch (fmt) {
257     /* color buffer */
258     case D3DFMT_P8:               retVal = 1; break;
259     case D3DFMT_R3G3B2:           retVal = 1; break;
260     case D3DFMT_R5G6B5:           retVal = 2; break;
261     case D3DFMT_X1R5G5B5:         retVal = 2; break;
262     case D3DFMT_A4R4G4B4:         retVal = 2; break;
263     case D3DFMT_X4R4G4B4:         retVal = 2; break;
264     case D3DFMT_A1R5G5B5:         retVal = 2; break;
265     case D3DFMT_R8G8B8:           retVal = 3; break;
266     case D3DFMT_X8R8G8B8:         retVal = 4; break;
267     case D3DFMT_A8R8G8B8:         retVal = 4; break;
268     /* depth/stencil buffer */
269     case D3DFMT_D16_LOCKABLE:     retVal = 2; break;
270     case D3DFMT_D16:              retVal = 2; break;
271     case D3DFMT_D15S1:            retVal = 2; break;
272     case D3DFMT_D24X4S4:          retVal = 4; break;
273     case D3DFMT_D24S8:            retVal = 4; break;
274     case D3DFMT_D24X8:            retVal = 4; break;
275     case D3DFMT_D32:              retVal = 4; break;
276     /* unknown */                                 
277     case D3DFMT_UNKNOWN:
278       /* Guess at the highest value of the above */
279       TRACE("D3DFMT_UNKNOWN - Guessing at 4 bytes/pixel %u\n", fmt);
280       retVal = 4;
281       break;
282
283     default:
284       FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
285       retVal = 4;
286     }
287     TRACE("bytes/Pxl for fmt(%u,%s) = %d\n", fmt, debug_d3dformat(fmt), retVal);
288     return retVal;
289 }
290
291 GLint D3DFmt2GLIntFmt(IDirect3DDevice8Impl* This, D3DFORMAT fmt) {
292     GLint retVal;
293
294     switch (fmt) {
295     case D3DFMT_P8:               retVal = GL_COLOR_INDEX8_EXT; break;
296     case D3DFMT_A8P8:             retVal = GL_COLOR_INDEX8_EXT; break;
297
298     case D3DFMT_A4R4G4B4:         retVal = GL_RGBA4; break;
299     case D3DFMT_A8R8G8B8:         retVal = GL_RGBA8; break;
300     case D3DFMT_X8R8G8B8:         retVal = GL_RGB8; break;
301     case D3DFMT_R8G8B8:           retVal = GL_RGB8; break;
302     case D3DFMT_R5G6B5:           retVal = GL_RGB5; break; /* fixme: internal format 6 for g? */
303     case D3DFMT_A1R5G5B5:         retVal = GL_RGB5_A1; break;
304     default:
305         FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
306         retVal = GL_RGB8;
307     }
308 #if defined(GL_EXT_texture_compression_s3tc)
309     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
310       switch (fmt) {
311       case D3DFMT_DXT1:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
312       case D3DFMT_DXT3:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
313       case D3DFMT_DXT5:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
314       default:
315         /* stupid compiler */
316         break;
317       }
318     }
319 #endif
320     TRACE("fmt2glintFmt for fmt(%u,%s) = %x\n", fmt, debug_d3dformat(fmt), retVal);
321     return retVal;
322 }
323
324 GLenum D3DFmt2GLFmt(IDirect3DDevice8Impl* This, D3DFORMAT fmt) {
325     GLenum retVal;
326
327     switch (fmt) {
328     case D3DFMT_P8:               retVal = GL_COLOR_INDEX; break;
329     case D3DFMT_A8P8:             retVal = GL_COLOR_INDEX; break;
330
331     case D3DFMT_A4R4G4B4:         retVal = GL_BGRA; break;
332     case D3DFMT_A8R8G8B8:         retVal = GL_BGRA; break;
333     case D3DFMT_X8R8G8B8:         retVal = GL_BGRA; break;
334     case D3DFMT_R8G8B8:           retVal = GL_BGR; break;
335     case D3DFMT_R5G6B5:           retVal = GL_RGB; break;
336     case D3DFMT_A1R5G5B5:         retVal = GL_BGRA; break;
337     default:
338         FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
339         retVal = GL_BGR;
340     }
341 #if defined(GL_EXT_texture_compression_s3tc)
342     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
343       switch (fmt) {
344       case D3DFMT_DXT1:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
345       case D3DFMT_DXT3:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
346       case D3DFMT_DXT5:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
347       default:
348         /* stupid compiler */
349         break;
350       }
351     }
352 #endif
353     TRACE("fmt2glFmt for fmt(%u,%s) = %x\n", fmt, debug_d3dformat(fmt), retVal);
354     return retVal;
355 }
356
357 GLenum D3DFmt2GLType(IDirect3DDevice8Impl* This, D3DFORMAT fmt) {
358     GLenum retVal;
359
360     switch (fmt) {
361     case D3DFMT_P8:               retVal = GL_UNSIGNED_BYTE; break;
362     case D3DFMT_A8P8:             retVal = GL_UNSIGNED_BYTE; break;
363
364     case D3DFMT_A4R4G4B4:         retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break;
365     case D3DFMT_A8R8G8B8:         retVal = GL_UNSIGNED_BYTE; break;
366     case D3DFMT_X8R8G8B8:         retVal = GL_UNSIGNED_BYTE; break;
367     case D3DFMT_R5G6B5:           retVal = GL_UNSIGNED_SHORT_5_6_5; break;
368     case D3DFMT_R8G8B8:           retVal = GL_UNSIGNED_BYTE; break;
369     case D3DFMT_A1R5G5B5:         retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break;
370     default:
371         FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
372         retVal = GL_UNSIGNED_BYTE;
373     }
374 #if defined(GL_EXT_texture_compression_s3tc)
375     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
376       switch (fmt) {
377       case D3DFMT_DXT1:             retVal = 0; break;
378       case D3DFMT_DXT3:             retVal = 0; break;
379       case D3DFMT_DXT5:             retVal = 0; break;
380       default:
381         /* stupid compiler */
382         break;
383       }
384     }
385 #endif
386     TRACE("fmt2glType for fmt(%u,%s) = %x\n", fmt, debug_d3dformat(fmt), retVal);
387     return retVal;
388 }
389
390 int SOURCEx_RGB_EXT(DWORD arg) {
391     switch(arg) {
392     case D3DTSS_COLORARG0: return GL_SOURCE2_RGB_EXT;
393     case D3DTSS_COLORARG1: return GL_SOURCE0_RGB_EXT;
394     case D3DTSS_COLORARG2: return GL_SOURCE1_RGB_EXT;
395     case D3DTSS_ALPHAARG0:
396     case D3DTSS_ALPHAARG1:
397     case D3DTSS_ALPHAARG2:
398     default:
399         FIXME("Invalid arg %ld\n", arg);
400         return GL_SOURCE0_RGB_EXT;
401     }
402 }
403
404 int OPERANDx_RGB_EXT(DWORD arg) {
405     switch(arg) {
406     case D3DTSS_COLORARG0: return GL_OPERAND2_RGB_EXT;
407     case D3DTSS_COLORARG1: return GL_OPERAND0_RGB_EXT;
408     case D3DTSS_COLORARG2: return GL_OPERAND1_RGB_EXT;
409     case D3DTSS_ALPHAARG0:
410     case D3DTSS_ALPHAARG1:
411     case D3DTSS_ALPHAARG2:
412     default:
413         FIXME("Invalid arg %ld\n", arg);
414         return GL_OPERAND0_RGB_EXT;
415     }
416 }
417
418 int SOURCEx_ALPHA_EXT(DWORD arg) {
419     switch(arg) {
420     case D3DTSS_ALPHAARG0:  return GL_SOURCE2_ALPHA_EXT;
421     case D3DTSS_ALPHAARG1:  return GL_SOURCE0_ALPHA_EXT;
422     case D3DTSS_ALPHAARG2:  return GL_SOURCE1_ALPHA_EXT;
423     case D3DTSS_COLORARG0:
424     case D3DTSS_COLORARG1:
425     case D3DTSS_COLORARG2:
426     default:
427         FIXME("Invalid arg %ld\n", arg);
428         return GL_SOURCE0_ALPHA_EXT;
429     }
430 }
431
432 int OPERANDx_ALPHA_EXT(DWORD arg) {
433     switch(arg) {
434     case D3DTSS_ALPHAARG0:  return GL_OPERAND2_ALPHA_EXT;
435     case D3DTSS_ALPHAARG1:  return GL_OPERAND0_ALPHA_EXT;
436     case D3DTSS_ALPHAARG2:  return GL_OPERAND1_ALPHA_EXT;
437     case D3DTSS_COLORARG0:
438     case D3DTSS_COLORARG1:
439     case D3DTSS_COLORARG2:
440     default:
441         FIXME("Invalid arg %ld\n", arg);
442         return GL_OPERAND0_ALPHA_EXT;
443     }
444 }
445
446 GLenum StencilOp(DWORD op) {
447     switch(op) {                
448     case D3DSTENCILOP_KEEP    : return GL_KEEP;
449     case D3DSTENCILOP_ZERO    : return GL_ZERO;
450     case D3DSTENCILOP_REPLACE : return GL_REPLACE;
451     case D3DSTENCILOP_INCRSAT : return GL_INCR;
452     case D3DSTENCILOP_DECRSAT : return GL_DECR;
453     case D3DSTENCILOP_INVERT  : return GL_INVERT; 
454 #if defined(GL_VERSION_1_4)
455     case D3DSTENCILOP_INCR    : return GL_INCR_WRAP;
456     case D3DSTENCILOP_DECR    : return GL_DECR_WRAP;
457 #elif defined(GL_EXT_stencil_wrap)
458     case D3DSTENCILOP_INCR    : return GL_INCR_WRAP_EXT;
459     case D3DSTENCILOP_DECR    : return GL_DECR_WRAP_EXT;
460 #else
461     case D3DSTENCILOP_INCR    : FIXME("Unsupported stencil op D3DSTENCILOP_INCR\n");
462                                 return GL_INCR; /* Fixme - needs to support wrap */
463     case D3DSTENCILOP_DECR    : FIXME("Unsupported stencil op D3DSTENCILOP_DECR\n");
464                                 return GL_DECR; /* Fixme - needs to support wrap */
465 #endif
466     default:
467         FIXME("Invalid stencil op %ld\n", op);
468         return GL_ALWAYS;
469     }
470 }
471
472 /**
473  * @nodoc: todo
474  */
475 void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand) 
476 {
477   BOOL isAlphaReplicate = FALSE;
478   BOOL isComplement     = FALSE;
479   
480   *operand = GL_SRC_COLOR;
481   *source = GL_TEXTURE;
482   
483   /* Catch alpha replicate */
484   if (iValue & D3DTA_ALPHAREPLICATE) {
485     iValue = iValue & ~D3DTA_ALPHAREPLICATE;
486     isAlphaReplicate = TRUE;
487   }
488   
489   /* Catch Complement */
490   if (iValue & D3DTA_COMPLEMENT) {
491     iValue = iValue & ~D3DTA_COMPLEMENT;
492     isComplement = TRUE;
493   }
494   
495   /* Calculate the operand */
496   if (isAlphaReplicate && !isComplement) {
497     *operand = GL_SRC_ALPHA;
498   } else if (isAlphaReplicate && isComplement) {
499     *operand = GL_ONE_MINUS_SRC_ALPHA;
500   } else if (isComplement) {
501     if (isAlphaArg) {
502       *operand = GL_ONE_MINUS_SRC_ALPHA;
503     } else {
504       *operand = GL_ONE_MINUS_SRC_COLOR;
505     }
506   } else {
507     if (isAlphaArg) {
508       *operand = GL_SRC_ALPHA;
509     } else {
510       *operand = GL_SRC_COLOR;
511     }
512   }
513   
514   /* Calculate the source */
515   switch (iValue & D3DTA_SELECTMASK) {
516   case D3DTA_CURRENT:   *source  = GL_PREVIOUS_EXT;
517     break;
518   case D3DTA_DIFFUSE:   *source  = GL_PRIMARY_COLOR_EXT;
519     break;
520   case D3DTA_TEXTURE:   *source  = GL_TEXTURE;
521     break;
522   case D3DTA_TFACTOR:   *source  = GL_CONSTANT_EXT;
523     break;
524   case D3DTA_SPECULAR:
525     /**
526      * According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
527      * isnt supported until base GL supports it
528      * There is no concept of temp registers as far as I can tell
529      */
530
531   default:
532     FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
533     *source = GL_TEXTURE;
534   }
535 }
536
537 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
538 #if defined (GL_VERSION_1_3)
539   #define useext(A) A
540   #define combine_ext 1
541 #elif defined (GL_EXT_texture_env_combine)
542   #define useext(A) A##_EXT
543   #define combine_ext 1
544 #elif defined (GL_ARB_texture_env_combine)
545   #define useext(A) A##_ARB
546   #define combine_ext 1
547 #else
548   #undef combine_ext
549 #endif
550
551 #if !defined(combine_ext)
552 void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
553
554         FIXME("Requires opengl combine extensions to work\n");
555         return;
556 }
557 #else
558 /* Setup the texture operations texture stage states */
559 void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
560 {
561         GLenum src1, src2, src3;
562         GLenum opr1, opr2, opr3;
563         GLenum comb_target;
564         GLenum src0_target, src1_target, src2_target;
565         GLenum opr0_target, opr1_target, opr2_target;
566         GLenum scal_target;
567         GLenum opr=0, invopr, src3_target, opr3_target;
568         BOOL Handled = FALSE;
569         ICOM_THIS(IDirect3DDevice8Impl,iface);
570
571         TRACE("Alpha?(%d), Stage:%d Op(%d), a1(%ld), a2(%ld), a3(%ld)\n", isAlpha, Stage, op, arg1, arg2, arg3);
572         if (op == D3DTOP_DISABLE) return;
573
574         if (isAlpha) {
575                 comb_target = useext(GL_COMBINE_ALPHA);
576                 src0_target = useext(GL_SOURCE0_ALPHA);
577                 src1_target = useext(GL_SOURCE1_ALPHA);
578                 src2_target = useext(GL_SOURCE2_ALPHA);
579                 opr0_target = useext(GL_OPERAND0_ALPHA);
580                 opr1_target = useext(GL_OPERAND1_ALPHA);
581                 opr2_target = useext(GL_OPERAND2_ALPHA);
582                 scal_target = useext(GL_ALPHA_SCALE);
583         }
584         else {
585                 comb_target = useext(GL_COMBINE_RGB);
586                 src0_target = useext(GL_SOURCE0_RGB);
587                 src1_target = useext(GL_SOURCE1_RGB);
588                 src2_target = useext(GL_SOURCE2_RGB);
589                 opr0_target = useext(GL_OPERAND0_RGB);
590                 opr1_target = useext(GL_OPERAND1_RGB);
591                 opr2_target = useext(GL_OPERAND2_RGB);
592                 scal_target = useext(GL_RGB_SCALE);
593         }
594
595         /* From MSDN (D3DTSS_ALPHAARG1) : 
596            The default argument is D3DTA_TEXTURE. If no texture is set for this stage, 
597                    then the default argument is D3DTA_DIFFUSE.
598                    FIXME? If texture added/removed, may need to reset back as well?    */
599         if (isAlpha && Stage==0 && This->StateBlock->textures[Stage] == NULL && arg1 == D3DTA_TEXTURE) {
600             GetSrcAndOpFromValue(D3DTA_DIFFUSE, isAlpha, &src1, &opr1);  
601         } else {
602             GetSrcAndOpFromValue(arg1, isAlpha, &src1, &opr1);
603         }
604         GetSrcAndOpFromValue(arg2, isAlpha, &src2, &opr2);
605         GetSrcAndOpFromValue(arg3, isAlpha, &src3, &opr3);
606         
607         TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
608
609         Handled = TRUE; /* Assume will be handled */
610         switch (op) {
611         case D3DTOP_SELECTARG1:
612                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
613                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
614                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
615                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
616                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
617                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
618                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
619                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
620                 break;
621         case D3DTOP_SELECTARG2:
622                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
623                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
624                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
625                 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
626                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
627                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
628                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
629                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
630                 break;
631         case D3DTOP_MODULATE:
632                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
633                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
634                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
635                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
636                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
637                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
638                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
639                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
640                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
641                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
642                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
643                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
644                 break;
645         case D3DTOP_MODULATE2X:
646                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
647                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
648                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
649                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
650                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
651                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
652                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
653                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
654                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
655                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
656                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
657                 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
658                 break;
659         case D3DTOP_MODULATE4X:
660                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
661                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
662                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
663                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
664                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
665                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
666                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
667                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
668                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
669                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
670                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
671                 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
672                 break;
673         case D3DTOP_ADD:
674                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
675                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
676                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
677                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
678                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
679                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
680                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
681                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
682                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
683                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
684                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
685                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
686                 break;
687         case D3DTOP_ADDSIGNED:
688                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
689                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
690                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
691                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
692                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
693                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
694                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
695                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
696                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
697                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
698                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
699                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
700                 break;
701         case D3DTOP_ADDSIGNED2X:
702                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
703                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
704                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
705                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
706                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
707                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
708                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
709                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
710                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
711                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
712                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
713                 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
714                 break;
715         case D3DTOP_SUBTRACT:
716 #if defined(GL_VERSION_1_3) || defined (GL_ARB_texture_env_combine)
717                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT));
718                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
719                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
720                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
721                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
722                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
723                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
724                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
725                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
726                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
727                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
728                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
729 #else
730                 FIXME("This version of opengl does not support GL_SUBTRACT\n");
731 #endif
732                 break;
733         case D3DTOP_BLENDDIFFUSEALPHA:
734                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
735                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
736                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
737                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
738                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
739                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
740                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
741                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
742                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
743                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
744                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR);
745                 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
746                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
747                 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
748                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
749                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
750                 break;
751         case D3DTOP_BLENDTEXTUREALPHA:
752                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
753                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
754                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
755                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
756                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
757                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
758                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
759                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
760                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
761                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
762                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
763                 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
764                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
765                 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
766                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
767                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
768                 break;
769         case D3DTOP_BLENDFACTORALPHA:
770                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
771                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
772                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
773                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
774                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
775                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
776                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
777                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
778                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
779                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
780                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_CONSTANT);
781                 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
782                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
783                 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
784                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
785                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
786                 break;
787         case D3DTOP_BLENDCURRENTALPHA:
788                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
789                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
790                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
791                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
792                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
793                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
794                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
795                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
796                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
797                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
798                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PREVIOUS);
799                 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
800                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
801                 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
802                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
803                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
804                 break;
805         case D3DTOP_DOTPRODUCT3: 
806 #if defined(GL_EXT_texture_env_dot3) 
807                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
808                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
809 #elif defined(GL_ARB_texture_env_dot3)
810                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
811                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
812 #elif defined (GL_VERSION_1_3)
813                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);
814                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA");
815 #else
816                 FIXME("This version of opengl does not support GL_DOT3\n");
817 #endif
818                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
819                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
820                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
821                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
822                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
823                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
824                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
825                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
826                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
827                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
828                 break;
829         case D3DTOP_LERP:
830                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
831                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
832                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
833                 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
834                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
835                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
836                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
837                 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
838                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
839                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
840                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
841                 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
842                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, src1);
843                 checkGLcall("GL_TEXTURE_ENV, opr2_target, src1");
844                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
845                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
846                 break;
847         default:
848                 Handled = FALSE;
849         }
850         if (Handled) {
851 #if defined(GL_NV_texture_env_combine4)
852            /* Note: If COMBINE4 in effect cant go back to combine! */
853            if (isAlpha) {
854                switch (This->UpdateStateBlock->texture_state[Stage][D3DTSS_COLOROP])
855                {
856                case D3DTOP_ADDSMOOTH:
857                case D3DTOP_BLENDTEXTUREALPHAPM:
858                case D3DTOP_MODULATEALPHA_ADDCOLOR:
859                case D3DTOP_MODULATECOLOR_ADDALPHA:
860                case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
861                case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
862                case D3DTOP_MULTIPLYADD:
863                    FIXME("Cant have COMBINE4 and COMBINE in efferct together, alphaop=%d\n", op);
864                    return;
865                }
866            }
867 #endif
868            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
869            checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
870            return;
871         }
872
873         /* Other texture operations require special extensions: */
874 #if defined(GL_NV_texture_env_combine4)
875         if (isAlpha) {
876                 invopr = GL_ONE_MINUS_SRC_ALPHA;
877                 src3_target = GL_SOURCE3_ALPHA_NV;
878                 opr3_target = GL_OPERAND3_ALPHA_NV;
879         }
880         else {
881                 invopr = GL_ONE_MINUS_SRC_COLOR;
882                 src3_target = GL_SOURCE3_RGB_NV;
883                 opr3_target = GL_OPERAND3_RGB_NV;
884         }
885         Handled = TRUE; /* Again, assume handled */
886         switch (op) {
887         case D3DTOP_ADDSMOOTH:
888                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
889                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
890                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
891                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
892                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
893                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
894                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
895                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
896                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
897                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
898                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
899                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
900                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
901                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
902                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
903                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
904                 switch (opr1) {
905                 case GL_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_COLOR; break;
906                 case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_SRC_COLOR; break;
907                 case GL_SRC_ALPHA: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
908                 case GL_ONE_MINUS_SRC_ALPHA: opr1 = GL_SRC_ALPHA; break;
909                 }
910                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr1);
911                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
912                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
913                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
914                 break;
915         case D3DTOP_BLENDTEXTUREALPHAPM:
916                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
917                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
918                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
919                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
920                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
921                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
922                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
923                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
924                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
925                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
926                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
927                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
928                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
929                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
930                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
931                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
932                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
933                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
934                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
935                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
936                 break;
937         case D3DTOP_MODULATEALPHA_ADDCOLOR:
938                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
939                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");  /* Add = a0*a1 + a2*a3 */
940                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);        /*   a0 = src1/opr1    */
941                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
942                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
943                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");    /*   a1 = 1 (see docs) */
944                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
945                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
946                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);      
947                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");  
948                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);        /*   a2 = arg2         */
949                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
950                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
951                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");     /*  a3 = src1 alpha   */
952                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
953                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
954                 switch (opr1) {
955                 case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
956                 case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
957                 }
958                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr1);
959                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
960                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
961                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
962                 break;
963         case D3DTOP_MODULATECOLOR_ADDALPHA:
964                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
965                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
966                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
967                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
968                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
969                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
970                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
971                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
972                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
973                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
974                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
975                 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
976                 switch (opr1) {
977                 case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
978                 case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
979                 }
980                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
981                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr1");
982                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
983                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
984                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
985                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
986                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
987                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
988                 break;
989         case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
990                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
991                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
992                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
993                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
994                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
995                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
996                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
997                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
998                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
999                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1000                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1001                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1002                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1003                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1004                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
1005                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
1006                 switch (opr1) {
1007                 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1008                 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
1009                 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1010                 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
1011                 }
1012                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1013                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1014                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1015                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1016                 break;
1017         case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
1018                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1019                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1020                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1021                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1022                 switch (opr1) {
1023                 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
1024                 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
1025                 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1026                 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
1027                 }
1028                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
1029                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
1030                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1031                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1032                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1033                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1034                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
1035                 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
1036                 switch (opr1) {
1037                 case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
1038                 case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
1039                 }
1040                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
1041                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr1");
1042                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1043                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1044                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
1045                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
1046                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1047                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1048                 break;
1049         case D3DTOP_MULTIPLYADD:
1050                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1051                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1052                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1053                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1054                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1055                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1056                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1057                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1058                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1059                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1060                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1061                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1062                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1063                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1064                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src3);
1065                 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
1066                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr3);
1067                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
1068                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1069                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1070                 break;
1071
1072         default:
1073                 Handled = FALSE;
1074         }
1075         if (Handled) {
1076             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
1077             checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
1078             return;
1079         }
1080 #endif /* GL_NV_texture_env_combine4 */
1081
1082         /* After all the extensions, if still unhandled, report fixme */
1083         FIXME("Unhandled texture operation %d\n", op);
1084 }
1085 #endif