When decoding a signed cert, make sure it's really a cert.
[wine] / dlls / d3d8 / surface.c
1 /*
2  * IDirect3DSurface8 implementation
3  *
4  * Copyright 2002-2004 Jason Edmeades
5  * Copyright 2002-2003 Raphael Junqueira
6  * Copyright 2004 Christian Costa
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdio.h>
28
29 #define COBJMACROS
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winuser.h"
36 #include "wingdi.h"
37 #include "wine/debug.h"
38
39 #include "d3d8_private.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
42
43 /* IDirect3DVolume IUnknown parts follow: */
44 HRESULT WINAPI IDirect3DSurface8Impl_QueryInterface(LPDIRECT3DSURFACE8 iface,REFIID riid,LPVOID *ppobj)
45 {
46     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
47
48     if (IsEqualGUID(riid, &IID_IUnknown)
49         || IsEqualGUID(riid, &IID_IDirect3DSurface8)) {
50         IDirect3DSurface8Impl_AddRef(iface);
51         *ppobj = This;
52         return D3D_OK;
53     }
54
55     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
56     return E_NOINTERFACE;
57 }
58
59 ULONG WINAPI IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) {
60     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
61     ULONG ref = InterlockedIncrement(&This->ref);
62
63     TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
64
65     return ref;
66 }
67
68 ULONG WINAPI IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) {
69     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
70     ULONG ref = InterlockedDecrement(&This->ref);
71
72     TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
73
74     if (ref == 0) {
75       HeapFree(GetProcessHeap(), 0, This->allocatedMemory);
76       HeapFree(GetProcessHeap(), 0, This);
77     }
78     return ref;
79 }
80
81 /* IDirect3DSurface8: */
82 HRESULT WINAPI IDirect3DSurface8Impl_GetDevice(LPDIRECT3DSURFACE8 iface, IDirect3DDevice8** ppDevice) {
83     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
84     TRACE("(%p) : returning %p\n", This, This->Device);
85     *ppDevice = (LPDIRECT3DDEVICE8) This->Device;
86     /**
87      * Note  Calling this method will increase the internal reference count 
88      * on the IDirect3DDevice8 interface. 
89      */
90     IDirect3DDevice8Impl_AddRef(*ppDevice);
91     return D3D_OK;
92 }
93
94 HRESULT WINAPI IDirect3DSurface8Impl_SetPrivateData(LPDIRECT3DSURFACE8 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
95     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
96     FIXME("(%p) : stub\n", This);    
97     return D3D_OK;
98 }
99
100 HRESULT WINAPI IDirect3DSurface8Impl_GetPrivateData(LPDIRECT3DSURFACE8 iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
101     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
102     FIXME("(%p) : stub\n", This);    
103     return D3D_OK;
104 }
105
106 HRESULT WINAPI IDirect3DSurface8Impl_FreePrivateData(LPDIRECT3DSURFACE8 iface, REFGUID refguid) {
107     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
108     FIXME("(%p) : stub\n", This);    
109     return D3D_OK;
110 }
111
112 HRESULT WINAPI IDirect3DSurface8Impl_GetContainer(LPDIRECT3DSURFACE8 iface, REFIID riid, void** ppContainer) {
113     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
114     HRESULT res;
115     res = IUnknown_QueryInterface(This->Container, riid, ppContainer);
116     if (E_NOINTERFACE == res) { 
117       /**
118        * If the surface is created using CreateImageSurface, CreateRenderTarget, 
119        * or CreateDepthStencilSurface, the surface is considered stand alone. In this case, 
120        * GetContainer will return the Direct3D device used to create the surface. 
121        */
122       res = IUnknown_QueryInterface(This->Container, &IID_IDirect3DDevice8, ppContainer);
123     }
124     TRACE("(%p) : returning %p\n", This, *ppContainer);
125     return res;
126 }
127
128 HRESULT WINAPI IDirect3DSurface8Impl_GetDesc(LPDIRECT3DSURFACE8 iface, D3DSURFACE_DESC *pDesc) {
129     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
130
131     TRACE("(%p) : copying into %p\n", This, pDesc);
132     memcpy(pDesc, &This->myDesc, sizeof(D3DSURFACE_DESC));
133     return D3D_OK;
134 }
135
136 HRESULT WINAPI IDirect3DSurface8Impl_LockRect(LPDIRECT3DSURFACE8 iface, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
137     HRESULT hr;
138     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
139   
140     /* fixme: should we really lock as such? */
141     if (This->inTexture && This->inPBuffer) {
142         FIXME("Warning: Surface is in texture memory or pbuffer\n");
143         This->inTexture = 0;
144         This->inPBuffer = 0;
145     }
146     
147     if (FALSE == This->lockable) {
148       /* Note: UpdateTextures calls CopyRects which calls this routine to populate the 
149             texture regions, and since the destination is an unlockable region we need
150             to tolerate this                                                           */
151       TRACE("Warning: trying to lock unlockable surf@%p\n", This);  
152       /*return D3DERR_INVALIDCALL; */
153     }
154
155     if (This == This->Device->backBuffer || This == This->Device->renderTarget || This == This->Device->frontBuffer || This->Device->depthStencilBuffer) {
156       if (This == This->Device->backBuffer) {
157         TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
158       } else if (This == This->Device->frontBuffer) {
159         TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
160       } else if (This == This->Device->renderTarget) {
161         TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
162       } else if (This == This->Device->depthStencilBuffer) {
163         TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
164       }
165     } else {
166       TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
167     }
168
169     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
170          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt3/5)      
171           ie pitch = (width/4) * bytes per block                                  */
172     if (This->myDesc.Format == D3DFMT_DXT1) /* DXT1 is 8 bytes per block */
173         pLockedRect->Pitch = (This->myDesc.Width/4) * 8;
174     else if (This->myDesc.Format == D3DFMT_DXT3 || This->myDesc.Format == D3DFMT_DXT5) /* DXT3/5 is 16 bytes per block */
175         pLockedRect->Pitch = (This->myDesc.Width/4) * 16;
176     else
177         pLockedRect->Pitch = This->bytesPerPixel * This->myDesc.Width;  /* Bytes / row */    
178
179     if (NULL == pRect) {
180       pLockedRect->pBits = This->allocatedMemory;
181       This->lockedRect.left   = 0;
182       This->lockedRect.top    = 0;
183       This->lockedRect.right  = This->myDesc.Width;
184       This->lockedRect.bottom = This->myDesc.Height;
185       TRACE("Locked Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", &This->lockedRect, This->lockedRect.left, This->lockedRect.top, This->lockedRect.right, This->lockedRect.bottom);
186     } else {
187       TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
188
189       if (This->myDesc.Format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
190           pLockedRect->pBits = This->allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel/2));
191       } else {
192           pLockedRect->pBits = This->allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
193       }
194       This->lockedRect.left   = pRect->left;
195       This->lockedRect.top    = pRect->top;
196       This->lockedRect.right  = pRect->right;
197       This->lockedRect.bottom = pRect->bottom;
198     }
199
200
201     if (0 == This->myDesc.Usage) { /* classic surface */
202
203       /* Nothing to do ;) */
204
205     } else if (D3DUSAGE_RENDERTARGET & This->myDesc.Usage && !(Flags&D3DLOCK_DISCARD)) { /* render surfaces */
206       
207       if (This == This->Device->backBuffer || This == This->Device->renderTarget || This == This->Device->frontBuffer) {
208         GLint  prev_store;
209         GLint  prev_read;
210         
211         ENTER_GL();
212
213         /**
214          * for render->surface copy begin to begin of allocatedMemory
215          * unlock can be more easy
216          */
217         pLockedRect->pBits = This->allocatedMemory;
218         
219         glFlush();
220         vcheckGLcall("glFlush");
221         glGetIntegerv(GL_READ_BUFFER, &prev_read);
222         vcheckGLcall("glIntegerv");
223         glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
224         vcheckGLcall("glIntegerv");
225
226         if (This == This->Device->backBuffer) {
227           glReadBuffer(GL_BACK);
228         } else if (This == This->Device->frontBuffer || This == This->Device->renderTarget) {
229           glReadBuffer(GL_FRONT);
230         } else if (This == This->Device->depthStencilBuffer) {
231           ERR("Stencil Buffer lock unsupported for now\n");
232         }
233         vcheckGLcall("glReadBuffer");
234
235         {
236           long j;
237           GLenum format = D3DFmt2GLFmt(This->Device, This->myDesc.Format);
238           GLenum type   = D3DFmt2GLType(This->Device, This->myDesc.Format);
239           for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
240             glReadPixels(This->lockedRect.left, 
241                          This->lockedRect.bottom - j - 1, 
242                          This->lockedRect.right - This->lockedRect.left, 
243                          1,
244                          format, 
245                          type, 
246                          (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
247             vcheckGLcall("glReadPixels");
248           }
249         }
250
251         glReadBuffer(prev_read);
252         vcheckGLcall("glReadBuffer");
253
254         LEAVE_GL();
255
256       } else {
257         FIXME("unsupported locking to Rendering surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
258       }
259
260     } else if (D3DUSAGE_DEPTHSTENCIL & This->myDesc.Usage) { /* stencil surfaces */
261
262       FIXME("TODO stencil depth surface locking surf@%p usage(%lu)\n", This, This->myDesc.Usage);
263
264     } else {
265       FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
266     }
267
268     if (Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY)) {
269       /* Don't dirtify */
270     } else {
271       /**
272        * Dirtify on lock
273        * as seen in msdn docs
274        */
275       IDirect3DSurface8Impl_AddDirtyRect(iface, &This->lockedRect);
276
277       /** Dirtify Container if needed */
278       if (NULL != This->Container) {
279         IDirect3DBaseTexture8* cont = NULL;
280         hr = IUnknown_QueryInterface(This->Container, &IID_IDirect3DBaseTexture8, (void**) &cont);
281         
282         if (SUCCEEDED(hr) && NULL != cont) {
283           IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
284           IDirect3DBaseTexture8_Release(cont);
285           cont = NULL;
286         }
287       }
288     }
289
290     TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Dirty);
291
292     This->locked = TRUE;
293     return D3D_OK;
294 }
295
296 HRESULT WINAPI IDirect3DSurface8Impl_UnlockRect(LPDIRECT3DSURFACE8 iface) {
297     GLint skipBytes = 0;
298     IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
299
300     if (FALSE == This->locked) {
301       ERR("trying to Unlock an unlocked surf@%p\n", This);  
302       return D3DERR_INVALIDCALL;
303     }
304
305     if (This == This->Device->backBuffer || This == This->Device->frontBuffer || This->Device->depthStencilBuffer || This == This->Device->renderTarget) {
306       if (This == This->Device->backBuffer) {
307         TRACE("(%p, backBuffer) : dirtyfied(%d)\n", This, This->Dirty);
308       } else if (This == This->Device->frontBuffer) {
309         TRACE("(%p, frontBuffer) : dirtyfied(%d)\n", This, This->Dirty);
310       } else if (This == This->Device->depthStencilBuffer) {
311         TRACE("(%p, stencilBuffer) : dirtyfied(%d)\n", This, This->Dirty);
312       } else if (This == This->Device->renderTarget) {
313         TRACE("(%p, renderTarget) : dirtyfied(%d)\n", This, This->Dirty);
314       }
315     } else {
316       TRACE("(%p) : dirtyfied(%d)\n", This, This->Dirty);
317     }
318
319     if (FALSE == This->Dirty) {
320       TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
321       goto unlock_end;
322     }
323
324     if (0 == This->myDesc.Usage) { /* classic surface */
325       /**
326        * nothing to do
327        * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
328        */
329     } else if (D3DUSAGE_RENDERTARGET & This->myDesc.Usage) { /* render surfaces */
330
331       if (This == This->Device->backBuffer || This == This->Device->frontBuffer || This == This->Device->renderTarget) {
332         GLint  prev_store;
333         GLint  prev_draw;
334         GLint  prev_rasterpos[4];
335
336         ENTER_GL();
337         
338         glFlush();
339         vcheckGLcall("glFlush");
340         glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
341         vcheckGLcall("glIntegerv");
342         glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
343         vcheckGLcall("glIntegerv");
344         glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
345         vcheckGLcall("glIntegerv");
346         glPixelZoom(1.0, -1.0);
347         vcheckGLcall("glPixelZoom");
348
349         /* glDrawPixels transforms the raster position as though it was a vertex -
350            we want to draw at screen position 0,0 - Set up ortho (rhw) mode as   
351            per drawprim (and leave set - it will sort itself out due to last_was_rhw */
352         if (!This->Device->last_was_rhw) {
353
354             double X, Y, height, width, minZ, maxZ;
355             This->Device->last_was_rhw = TRUE;
356
357             /* Transformed already into viewport coordinates, so we do not need transform
358                matrices. Reset all matrices to identity and leave the default matrix in world 
359                mode.                                                                         */
360             glMatrixMode(GL_MODELVIEW);
361             checkGLcall("glMatrixMode");
362             glLoadIdentity();
363             checkGLcall("glLoadIdentity");
364
365             glMatrixMode(GL_PROJECTION);
366             checkGLcall("glMatrixMode");
367             glLoadIdentity();
368             checkGLcall("glLoadIdentity");
369
370             /* Set up the viewport to be full viewport */
371             X      = This->Device->StateBlock->viewport.X;
372             Y      = This->Device->StateBlock->viewport.Y;
373             height = This->Device->StateBlock->viewport.Height;
374             width  = This->Device->StateBlock->viewport.Width;
375             minZ   = This->Device->StateBlock->viewport.MinZ;
376             maxZ   = This->Device->StateBlock->viewport.MaxZ;
377             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
378             glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
379             checkGLcall("glOrtho");
380
381             /* Window Coord 0 is the middle of the first pixel, so translate by half
382                a pixel (See comment above glTranslate below)                         */
383             glTranslatef(0.5, 0.5, 0);
384             checkGLcall("glTranslatef(0.5, 0.5, 0)");
385         }
386
387         if (This == This->Device->backBuffer) {
388           glDrawBuffer(GL_BACK);
389         } else if (This == This->Device->frontBuffer || This == This->Device->renderTarget) {
390           glDrawBuffer(GL_FRONT);
391         }
392         vcheckGLcall("glDrawBuffer");
393
394     /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
395     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
396     glPixelStorei(GL_UNPACK_ROW_LENGTH, This->myDesc.Width);
397
398     /* And back buffers are not blended */
399     glDisable(GL_BLEND);
400
401         glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
402         vcheckGLcall("glRasterPos2f");
403         switch (This->myDesc.Format) {
404         case D3DFMT_R5G6B5:
405           {
406             glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
407                          GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->allocatedMemory);
408             vcheckGLcall("glDrawPixels");
409           }
410           break;
411         case D3DFMT_R8G8B8:
412           {
413             glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
414                          GL_RGB, GL_UNSIGNED_BYTE, This->allocatedMemory);
415             vcheckGLcall("glDrawPixels");
416           }
417           break;
418         case D3DFMT_A8R8G8B8:
419           {
420             glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
421             vcheckGLcall("glPixelStorei");
422             glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
423                          GL_BGRA, GL_UNSIGNED_BYTE, This->allocatedMemory);
424             vcheckGLcall("glDrawPixels");
425             glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
426             vcheckGLcall("glPixelStorei");
427           }
428           break;
429         default:
430           FIXME("Unsupported Format %u in locking func\n", This->myDesc.Format);
431         }
432
433         glPixelZoom(1.0,1.0);
434         vcheckGLcall("glPixelZoom");
435         glDrawBuffer(prev_draw);
436         vcheckGLcall("glDrawBuffer");
437         glRasterPos3iv(&prev_rasterpos[0]);
438         vcheckGLcall("glRasterPos3iv");
439
440     /* Reset to previous pack row length / blending state */
441     glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
442     if (This->Device->StateBlock->renderstate[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
443
444         LEAVE_GL();
445
446         /** restore clean dirty state */
447         IDirect3DSurface8Impl_CleanDirtyRect(iface);
448
449       } else {
450         FIXME("unsupported unlocking to Rendering surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
451       }
452
453     } else if (D3DUSAGE_DEPTHSTENCIL & This->myDesc.Usage) { /* stencil surfaces */
454     
455       if (This == This->Device->depthStencilBuffer) {
456         FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->myDesc.Usage);
457       } else {
458         FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
459       }
460
461     } else {
462       FIXME("unsupported unlocking to surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
463     }
464
465 unlock_end:
466     This->locked = FALSE;
467     memset(&This->lockedRect, 0, sizeof(RECT));
468     return D3D_OK;
469 }
470
471
472 const IDirect3DSurface8Vtbl Direct3DSurface8_Vtbl =
473 {
474     IDirect3DSurface8Impl_QueryInterface,
475     IDirect3DSurface8Impl_AddRef,
476     IDirect3DSurface8Impl_Release,
477     IDirect3DSurface8Impl_GetDevice,
478     IDirect3DSurface8Impl_SetPrivateData,
479     IDirect3DSurface8Impl_GetPrivateData,
480     IDirect3DSurface8Impl_FreePrivateData,
481     IDirect3DSurface8Impl_GetContainer,
482     IDirect3DSurface8Impl_GetDesc,
483     IDirect3DSurface8Impl_LockRect,
484     IDirect3DSurface8Impl_UnlockRect,
485 };
486
487
488 HRESULT WINAPI IDirect3DSurface8Impl_LoadTexture(LPDIRECT3DSURFACE8 iface, UINT gl_target, UINT gl_level) {
489   IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
490
491   if (This->inTexture)
492     return D3D_OK;
493   if (This->inPBuffer) {
494     ENTER_GL();
495     if (gl_level != 0)
496       FIXME("Surface in texture is only supported for level 0\n");
497     else if (This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8 ||
498         This->myDesc.Format == D3DFMT_DXT1 || This->myDesc.Format == D3DFMT_DXT3 ||
499         This->myDesc.Format == D3DFMT_DXT5)
500       FIXME("Format %d not supported\n", This->myDesc.Format);
501     else {
502         glCopyTexImage2D(gl_target,
503                          0,
504                          D3DFmt2GLIntFmt(This->Device,
505                          This->myDesc.Format),
506                          0,
507                          0,/*This->surfaces[j][i]->myDesc.Height-1,*/
508                          This->myDesc.Width,
509                          This->myDesc.Height,
510                          0);
511         TRACE("Updating target %d\n", gl_target);
512         This->inTexture = TRUE;
513     }
514     LEAVE_GL();
515     return D3D_OK;
516   }
517   
518   if ((This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8) && 
519       !GL_SUPPORT_DEV(EXT_PALETTED_TEXTURE, This->Device)) {
520     /**
521      * wanted a paletted texture and not really support it in HW 
522      * so software emulation code begin
523      */
524     UINT i;
525     PALETTEENTRY* pal = This->Device->palettes[This->Device->currentPalette];
526     VOID* surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->myDesc.Width * This->myDesc.Height * sizeof(DWORD));
527     BYTE* dst = surface;
528     BYTE* src = (BYTE*) This->allocatedMemory;
529           
530     for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
531       BYTE color = *src++;
532       *dst++ = pal[color].peRed;
533       *dst++ = pal[color].peGreen;
534       *dst++ = pal[color].peBlue;
535       if (This->myDesc.Format == D3DFMT_A8P8)
536         *dst++ = pal[color].peFlags; 
537       else
538         *dst++ = 0xFF; 
539     }
540
541     ENTER_GL();
542     
543     TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
544           gl_target,
545           gl_level, 
546           GL_RGBA,
547           This->myDesc.Width, 
548           This->myDesc.Height, 
549           0, 
550           GL_RGBA,
551           GL_UNSIGNED_BYTE,
552           surface);
553     glTexImage2D(gl_target,
554                  gl_level, 
555                  GL_RGBA,
556                  This->myDesc.Width,
557                  This->myDesc.Height,
558                  0,
559                  GL_RGBA,
560                  GL_UNSIGNED_BYTE,
561                  surface);
562     checkGLcall("glTexImage2D");
563     HeapFree(GetProcessHeap(), 0, surface);
564
565     LEAVE_GL();
566
567     return D3D_OK;    
568   }
569
570   if (This->myDesc.Format == D3DFMT_DXT1 || 
571       This->myDesc.Format == D3DFMT_DXT3 || 
572       This->myDesc.Format == D3DFMT_DXT5) {
573     if (GL_SUPPORT_DEV(EXT_TEXTURE_COMPRESSION_S3TC, This->Device)) {
574       TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
575             gl_target, 
576             gl_level, 
577             D3DFmt2GLIntFmt(This->Device, This->myDesc.Format), 
578             This->myDesc.Width, 
579             This->myDesc.Height, 
580             0, 
581             This->myDesc.Size,
582             This->allocatedMemory);
583       
584       ENTER_GL();
585
586       GL_EXTCALL_DEV(glCompressedTexImage2DARB, This->Device)(gl_target, 
587                                                               gl_level, 
588                                                               D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
589                                                               This->myDesc.Width,
590                                                               This->myDesc.Height,
591                                                               0,
592                                                               This->myDesc.Size,
593                                                               This->allocatedMemory);
594       checkGLcall("glCommpressedTexTexImage2D");
595
596       LEAVE_GL();
597     } else {
598       FIXME("Using DXT1/3/5 without advertized support\n");
599     }
600   } else {
601
602     TRACE("Calling glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
603           gl_target, 
604           gl_level, 
605           debug_d3dformat(This->myDesc.Format),
606           D3DFmt2GLIntFmt(This->Device, This->myDesc.Format), 
607           This->myDesc.Width, 
608           This->myDesc.Height, 
609           0, 
610           D3DFmt2GLFmt(This->Device, This->myDesc.Format), 
611           D3DFmt2GLType(This->Device, This->myDesc.Format),
612           This->allocatedMemory);
613
614     ENTER_GL();
615
616     glTexImage2D(gl_target, 
617                  gl_level,
618                  D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
619                  This->myDesc.Width,
620                  This->myDesc.Height,
621                  0,
622                  D3DFmt2GLFmt(This->Device, This->myDesc.Format),
623                  D3DFmt2GLType(This->Device, This->myDesc.Format),
624                  This->allocatedMemory);
625     checkGLcall("glTexImage2D");
626
627     LEAVE_GL();
628
629 #if 0
630     {
631       static unsigned int gen = 0;
632       char buffer[4096];
633       ++gen;
634       if ((gen % 10) == 0) {
635         snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, gl_target, gl_level, gen);
636         IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This, buffer);
637       }
638       /*
639        * debugging crash code
640       if (gen == 250) {
641         void** test = NULL;
642         *test = 0;
643       }
644       */
645     }
646 #endif
647   }
648
649   return D3D_OK;
650 }
651
652 #include <errno.h>
653 HRESULT WINAPI IDirect3DSurface8Impl_SaveSnapshot(LPDIRECT3DSURFACE8 iface, const char* filename) {
654   FILE* f = NULL;
655   ULONG i;
656   IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
657
658   f = fopen(filename, "w+");
659   if (NULL == f) {
660     ERR("opening of %s failed with: %s\n", filename, strerror(errno));
661     return D3DERR_INVALIDCALL;
662   }
663
664   TRACE("opened %s with format %s\n", filename, debug_d3dformat(This->myDesc.Format));
665
666   fprintf(f, "P6\n%u %u\n255\n", This->myDesc.Width, This->myDesc.Height);
667   switch (This->myDesc.Format) {
668   case D3DFMT_X8R8G8B8:
669   case D3DFMT_A8R8G8B8:
670     {
671       DWORD color;
672       for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
673         color = ((DWORD*) This->allocatedMemory)[i];
674         fputc((color >> 16) & 0xFF, f);
675         fputc((color >>  8) & 0xFF, f);
676         fputc((color >>  0) & 0xFF, f);
677       }
678     }
679     break;
680   case D3DFMT_R8G8B8:
681     {
682       BYTE* color;
683       for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
684         color = ((BYTE*) This->allocatedMemory) + (3 * i);
685         fputc((color[0]) & 0xFF, f);
686         fputc((color[1]) & 0xFF, f);
687         fputc((color[2]) & 0xFF, f);
688       }
689     }
690     break;
691   case D3DFMT_A1R5G5B5: 
692     {
693       WORD color;
694       for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
695         color = ((WORD*) This->allocatedMemory)[i];
696         fputc(((color >> 10) & 0x1F) * 255 / 31, f);
697         fputc(((color >>  5) & 0x1F) * 255 / 31, f);
698         fputc(((color >>  0) & 0x1F) * 255 / 31, f);
699       }
700     }
701     break;
702   case D3DFMT_A4R4G4B4:
703     {
704       WORD color;
705       for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
706         color = ((WORD*) This->allocatedMemory)[i];
707         fputc(((color >>  8) & 0x0F) * 255 / 15, f);
708         fputc(((color >>  4) & 0x0F) * 255 / 15, f);
709         fputc(((color >>  0) & 0x0F) * 255 / 15, f);
710       }
711     }
712     break;
713
714   case D3DFMT_R5G6B5: 
715     {
716       WORD color;
717       for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
718         color = ((WORD*) This->allocatedMemory)[i];
719         fputc(((color >> 11) & 0x1F) * 255 / 31, f);
720         fputc(((color >>  5) & 0x3F) * 255 / 63, f);
721         fputc(((color >>  0) & 0x1F) * 255 / 31, f);
722       }
723     }
724     break;
725   default: 
726     FIXME("Unimplemented dump mode format(%u,%s)\n", This->myDesc.Format, debug_d3dformat(This->myDesc.Format));
727   }
728   fclose(f);
729   return D3D_OK;
730 }
731
732 HRESULT WINAPI IDirect3DSurface8Impl_CleanDirtyRect(LPDIRECT3DSURFACE8 iface) {
733   IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
734   This->Dirty = FALSE;
735   This->dirtyRect.left   = This->myDesc.Width;
736   This->dirtyRect.top    = This->myDesc.Height;
737   This->dirtyRect.right  = 0;
738   This->dirtyRect.bottom = 0;
739   return D3D_OK;
740 }
741
742 /**
743  * Raphael:
744  *   very stupid way to handle multiple dirty rects but it works :)
745  */
746 extern HRESULT WINAPI IDirect3DSurface8Impl_AddDirtyRect(LPDIRECT3DSURFACE8 iface, CONST RECT* pDirtyRect) {
747   IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
748   This->Dirty = TRUE;
749   if (NULL != pDirtyRect) {
750     This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
751     This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
752     This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
753     This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
754   } else {
755     This->dirtyRect.left   = 0;
756     This->dirtyRect.top    = 0;
757     This->dirtyRect.right  = This->myDesc.Width;
758     This->dirtyRect.bottom = This->myDesc.Height;
759   }
760   return D3D_OK;
761 }