2 * IWineD3DSurface Implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2004 Christian Costa
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.
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.
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
24 #include "wined3d_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface
);
27 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
29 /* *******************************************
30 IWineD3DSurface IUnknown parts follow
31 ******************************************* */
32 HRESULT WINAPI
IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface
*iface
, REFIID riid
, LPVOID
*ppobj
)
34 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
35 WARN("(%p)->(%s,%p) should not be called\n",This
,debugstr_guid(riid
),ppobj
);
39 ULONG WINAPI
IWineD3DSurfaceImpl_AddRef(IWineD3DSurface
*iface
) {
40 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
41 TRACE("(%p) : AddRef increasing from %ld\n", This
, This
->resource
.ref
);
42 IUnknown_AddRef(This
->resource
.parent
);
43 return InterlockedIncrement(&This
->resource
.ref
);
46 ULONG WINAPI
IWineD3DSurfaceImpl_Release(IWineD3DSurface
*iface
) {
47 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
49 TRACE("(%p) : Releasing from %ld\n", This
, This
->resource
.ref
);
50 ref
= InterlockedDecrement(&This
->resource
.ref
);
52 HeapFree(GetProcessHeap(), 0, This
->allocatedMemory
);
53 IWineD3DDevice_Release((IWineD3DDevice
*)This
->resource
.wineD3DDevice
);
54 HeapFree(GetProcessHeap(), 0, This
);
56 IUnknown_Release(This
->resource
.parent
); /* Released the reference to the d3dx object */
61 /* ****************************************************
62 IWineD3DSurface IWineD3DResource parts follow
63 **************************************************** */
64 HRESULT WINAPI
IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface
*iface
, IWineD3DDevice
** ppDevice
) {
65 return IWineD3DResource_GetDevice((IWineD3DResource
*)iface
, ppDevice
);
68 HRESULT WINAPI
IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface
*iface
, REFGUID refguid
, CONST
void* pData
, DWORD SizeOfData
, DWORD Flags
) {
69 return IWineD3DResource_SetPrivateData((IWineD3DResource
*)iface
, refguid
, pData
, SizeOfData
, Flags
);
72 HRESULT WINAPI
IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface
*iface
, REFGUID refguid
, void* pData
, DWORD
* pSizeOfData
) {
73 return IWineD3DResource_GetPrivateData((IWineD3DResource
*)iface
, refguid
, pData
, pSizeOfData
);
76 HRESULT WINAPI
IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface
*iface
, REFGUID refguid
) {
77 return IWineD3DResource_FreePrivateData((IWineD3DResource
*)iface
, refguid
);
80 DWORD WINAPI
IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface
*iface
, DWORD PriorityNew
) {
81 return IWineD3DResource_SetPriority((IWineD3DResource
*)iface
, PriorityNew
);
84 DWORD WINAPI
IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface
*iface
) {
85 return IWineD3DResource_GetPriority((IWineD3DResource
*)iface
);
88 void WINAPI
IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface
*iface
) {
89 return IWineD3DResource_PreLoad((IWineD3DResource
*)iface
);
92 D3DRESOURCETYPE WINAPI
IWineD3DSurfaceImpl_GetType(IWineD3DSurface
*iface
) {
93 return IWineD3DResource_GetType((IWineD3DResource
*)iface
);
96 HRESULT WINAPI
IWineD3DSurfaceImpl_GetParent(IWineD3DSurface
*iface
, IUnknown
**pParent
) {
97 return IWineD3DResource_GetParent((IWineD3DResource
*)iface
, pParent
);
100 /* ******************************************************
101 IWineD3DSurface IWineD3DSurface parts follow
102 ****************************************************** */
104 HRESULT WINAPI
IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface
*iface
, REFIID riid
, void** ppContainer
) {
105 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
108 * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
109 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
110 * GetContainer will return the Direct3D device used to create the surface.
112 WARN("Query of container implementation currently ignores riid\n");
113 *ppContainer
= This
->container
;
114 IUnknown_AddRef((IUnknown
*)*ppContainer
);
115 TRACE("(%p) : returning %p\n", This
, *ppContainer
);
119 HRESULT WINAPI
IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface
*iface
, WINED3DSURFACE_DESC
*pDesc
) {
120 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
122 TRACE("(%p) : copying into %p\n", This
, pDesc
);
123 *(pDesc
->Format
) = This
->currentDesc
.Format
;
124 *(pDesc
->Type
) = This
->currentDesc
.Type
;
125 *(pDesc
->Usage
) = This
->currentDesc
.Usage
;
126 *(pDesc
->Pool
) = This
->currentDesc
.Pool
;
127 *(pDesc
->MultiSampleType
) = This
->currentDesc
.MultiSampleType
;
128 *(pDesc
->MultiSampleQuality
) = This
->currentDesc
.MultiSampleQuality
;
129 *(pDesc
->Width
) = This
->currentDesc
.Width
;
130 *(pDesc
->Height
) = This
->currentDesc
.Height
;
134 HRESULT WINAPI
IWineD3DSurfaceImpl_LockRect(IWineD3DSurface
*iface
, D3DLOCKED_RECT
* pLockedRect
, CONST RECT
* pRect
, DWORD Flags
) {
135 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
137 /* fixme: should we really lock as such? */
138 if (This
->inTexture
&& This
->inPBuffer
) {
139 FIXME("Warning: Surface is in texture memory or pbuffer\n");
144 if (FALSE
== This
->lockable
) {
145 /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
146 texture regions, and since the destination is an unlockable region we need
148 TRACE("Warning: trying to lock unlockable surf@%p\n", This
);
149 /*return D3DERR_INVALIDCALL; */
152 if (This
== This
->resource
.wineD3DDevice
->backBuffer
|| This
== This
->resource
.wineD3DDevice
->renderTarget
|| This
== This
->resource
.wineD3DDevice
->frontBuffer
|| This
->resource
.wineD3DDevice
->depthStencilBuffer
) {
153 if (This
== This
->resource
.wineD3DDevice
->backBuffer
) {
154 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->allocatedMemory
);
155 } else if (This
== This
->resource
.wineD3DDevice
->frontBuffer
) {
156 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->allocatedMemory
);
157 } else if (This
== This
->resource
.wineD3DDevice
->renderTarget
) {
158 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->allocatedMemory
);
159 } else if (This
== This
->resource
.wineD3DDevice
->depthStencilBuffer
) {
160 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->allocatedMemory
);
163 TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->allocatedMemory
);
166 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
167 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt3/5)
168 ie pitch = (width/4) * bytes per block */
169 if (This
->currentDesc
.Format
== D3DFMT_DXT1
) /* DXT1 is 8 bytes per block */
170 pLockedRect
->Pitch
= (This
->currentDesc
.Width
/4) * 8;
171 else if (This
->currentDesc
.Format
== D3DFMT_DXT3
|| This
->currentDesc
.Format
== D3DFMT_DXT5
) /* DXT3/5 is 16 bytes per block */
172 pLockedRect
->Pitch
= (This
->currentDesc
.Width
/4) * 16;
174 pLockedRect
->Pitch
= This
->bytesPerPixel
* This
->currentDesc
.Width
; /* Bytes / row */
177 pLockedRect
->pBits
= This
->allocatedMemory
;
178 This
->lockedRect
.left
= 0;
179 This
->lockedRect
.top
= 0;
180 This
->lockedRect
.right
= This
->currentDesc
.Width
;
181 This
->lockedRect
.bottom
= This
->currentDesc
.Height
;
182 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
);
184 TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
186 if (This
->currentDesc
.Format
== D3DFMT_DXT1
) { /* DXT1 is half byte per pixel */
187 pLockedRect
->pBits
= This
->allocatedMemory
+ (pLockedRect
->Pitch
* pRect
->top
) + ((pRect
->left
* This
->bytesPerPixel
/2));
189 pLockedRect
->pBits
= This
->allocatedMemory
+ (pLockedRect
->Pitch
* pRect
->top
) + (pRect
->left
* This
->bytesPerPixel
);
191 This
->lockedRect
.left
= pRect
->left
;
192 This
->lockedRect
.top
= pRect
->top
;
193 This
->lockedRect
.right
= pRect
->right
;
194 This
->lockedRect
.bottom
= pRect
->bottom
;
198 if (0 == This
->currentDesc
.Usage
) { /* classic surface */
200 /* Nothing to do ;) */
202 } else if (D3DUSAGE_RENDERTARGET
& This
->currentDesc
.Usage
&& !(Flags
&D3DLOCK_DISCARD
)) { /* render surfaces */
204 if (This
== This
->resource
.wineD3DDevice
->backBuffer
|| This
== This
->resource
.wineD3DDevice
->renderTarget
|| This
== This
->resource
.wineD3DDevice
->frontBuffer
) {
211 * for render->surface copy begin to begin of allocatedMemory
212 * unlock can be more easy
214 pLockedRect
->pBits
= This
->allocatedMemory
;
217 vcheckGLcall("glFlush");
218 glGetIntegerv(GL_READ_BUFFER
, &prev_read
);
219 vcheckGLcall("glIntegerv");
220 glGetIntegerv(GL_PACK_SWAP_BYTES
, &prev_store
);
221 vcheckGLcall("glIntegerv");
223 if (This
== This
->resource
.wineD3DDevice
->backBuffer
) {
224 glReadBuffer(GL_BACK
);
225 } else if (This
== This
->resource
.wineD3DDevice
->frontBuffer
|| This
== This
->resource
.wineD3DDevice
->renderTarget
) {
226 glReadBuffer(GL_FRONT
);
227 } else if (This
== This
->resource
.wineD3DDevice
->depthStencilBuffer
) {
228 ERR("Stencil Buffer lock unsupported for now\n");
230 vcheckGLcall("glReadBuffer");
234 GLenum format
= D3DFmt2GLFmt(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
);
235 GLenum type
= D3DFmt2GLType(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
);
236 for (j
= This
->lockedRect
.top
; j
< This
->lockedRect
.bottom
- This
->lockedRect
.top
; ++j
) {
237 glReadPixels(This
->lockedRect
.left
,
238 This
->lockedRect
.bottom
- j
- 1,
239 This
->lockedRect
.right
- This
->lockedRect
.left
,
243 (char *)pLockedRect
->pBits
+ (pLockedRect
->Pitch
* (j
-This
->lockedRect
.top
)));
244 vcheckGLcall("glReadPixels");
248 glReadBuffer(prev_read
);
249 vcheckGLcall("glReadBuffer");
254 FIXME("unsupported locking to Rendering surface surf@%p usage(%lu)\n", This
, This
->currentDesc
.Usage
);
257 } else if (D3DUSAGE_DEPTHSTENCIL
& This
->currentDesc
.Usage
) { /* stencil surfaces */
259 FIXME("TODO stencil depth surface locking surf@%p usage(%lu)\n", This
, This
->currentDesc
.Usage
);
262 FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This
, This
->currentDesc
.Usage
);
265 if (Flags
& (D3DLOCK_NO_DIRTY_UPDATE
| D3DLOCK_READONLY
)) {
270 * as seen in msdn docs
272 IWineD3DSurface_AddDirtyRect(iface
, &This
->lockedRect
);
274 /** Dirtify Container if needed */
275 if ((NULL
!= This
->container
) && ((IWineD3DDeviceImpl
*)This
->container
!= This
->resource
.wineD3DDevice
)) {
276 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture
*)This
->container
, TRUE
);
280 TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect
->pBits
, pLockedRect
->Pitch
, This
->Dirty
);
286 HRESULT WINAPI
IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface
*iface
) {
288 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
290 if (FALSE
== This
->locked
) {
291 ERR("trying to Unlock an unlocked surf@%p\n", This
);
292 return D3DERR_INVALIDCALL
;
295 if (This
== This
->resource
.wineD3DDevice
->backBuffer
|| This
== This
->resource
.wineD3DDevice
->frontBuffer
|| This
->resource
.wineD3DDevice
->depthStencilBuffer
|| This
== This
->resource
.wineD3DDevice
->renderTarget
) {
296 if (This
== This
->resource
.wineD3DDevice
->backBuffer
) {
297 TRACE("(%p, backBuffer) : dirtyfied(%d)\n", This
, This
->Dirty
);
298 } else if (This
== This
->resource
.wineD3DDevice
->frontBuffer
) {
299 TRACE("(%p, frontBuffer) : dirtyfied(%d)\n", This
, This
->Dirty
);
300 } else if (This
== This
->resource
.wineD3DDevice
->depthStencilBuffer
) {
301 TRACE("(%p, stencilBuffer) : dirtyfied(%d)\n", This
, This
->Dirty
);
302 } else if (This
== This
->resource
.wineD3DDevice
->renderTarget
) {
303 TRACE("(%p, renderTarget) : dirtyfied(%d)\n", This
, This
->Dirty
);
306 TRACE("(%p) : dirtyfied(%d)\n", This
, This
->Dirty
);
309 if (FALSE
== This
->Dirty
) {
310 TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This
);
314 if (0 == This
->currentDesc
.Usage
) { /* classic surface */
317 * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
319 } else if (D3DUSAGE_RENDERTARGET
& This
->currentDesc
.Usage
) { /* render surfaces */
321 if (This
== This
->resource
.wineD3DDevice
->backBuffer
|| This
== This
->resource
.wineD3DDevice
->frontBuffer
|| This
== This
->resource
.wineD3DDevice
->renderTarget
) {
324 GLint prev_rasterpos
[4];
329 vcheckGLcall("glFlush");
330 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
331 vcheckGLcall("glIntegerv");
332 glGetIntegerv(GL_PACK_SWAP_BYTES
, &prev_store
);
333 vcheckGLcall("glIntegerv");
334 glGetIntegerv(GL_CURRENT_RASTER_POSITION
, &prev_rasterpos
[0]);
335 vcheckGLcall("glIntegerv");
336 glPixelZoom(1.0, -1.0);
337 vcheckGLcall("glPixelZoom");
339 /* glDrawPixels transforms the raster position as though it was a vertex -
340 we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
341 per drawprim (and leave set - it will sort itself out due to last_was_rhw */
342 if (!This
->resource
.wineD3DDevice
->last_was_rhw
) {
344 double X
, Y
, height
, width
, minZ
, maxZ
;
345 This
->resource
.wineD3DDevice
->last_was_rhw
= TRUE
;
347 /* Transformed already into viewport coordinates, so we do not need transform
348 matrices. Reset all matrices to identity and leave the default matrix in world
350 glMatrixMode(GL_MODELVIEW
);
351 checkGLcall("glMatrixMode");
353 checkGLcall("glLoadIdentity");
355 glMatrixMode(GL_PROJECTION
);
356 checkGLcall("glMatrixMode");
358 checkGLcall("glLoadIdentity");
360 /* Set up the viewport to be full viewport */
361 X
= This
->resource
.wineD3DDevice
->stateBlock
->viewport
.X
;
362 Y
= This
->resource
.wineD3DDevice
->stateBlock
->viewport
.Y
;
363 height
= This
->resource
.wineD3DDevice
->stateBlock
->viewport
.Height
;
364 width
= This
->resource
.wineD3DDevice
->stateBlock
->viewport
.Width
;
365 minZ
= This
->resource
.wineD3DDevice
->stateBlock
->viewport
.MinZ
;
366 maxZ
= This
->resource
.wineD3DDevice
->stateBlock
->viewport
.MaxZ
;
367 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width
, height
, -minZ
, -maxZ
);
368 glOrtho(X
, X
+ width
, Y
+ height
, Y
, -minZ
, -maxZ
);
369 checkGLcall("glOrtho");
371 /* Window Coord 0 is the middle of the first pixel, so translate by half
372 a pixel (See comment above glTranslate below) */
373 glTranslatef(0.5, 0.5, 0);
374 checkGLcall("glTranslatef(0.5, 0.5, 0)");
377 if (This
== This
->resource
.wineD3DDevice
->backBuffer
) {
378 glDrawBuffer(GL_BACK
);
379 } else if (This
== This
->resource
.wineD3DDevice
->frontBuffer
|| This
== This
->resource
.wineD3DDevice
->renderTarget
) {
380 glDrawBuffer(GL_FRONT
);
382 vcheckGLcall("glDrawBuffer");
384 /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
385 glGetIntegerv(GL_UNPACK_ROW_LENGTH
, &skipBytes
);
386 glPixelStorei(GL_UNPACK_ROW_LENGTH
, This
->currentDesc
.Width
);
388 /* And back buffers are not blended */
391 glRasterPos3i(This
->lockedRect
.left
, This
->lockedRect
.top
, 1);
392 vcheckGLcall("glRasterPos2f");
393 switch (This
->currentDesc
.Format
) {
396 glDrawPixels(This
->lockedRect
.right
- This
->lockedRect
.left
, (This
->lockedRect
.bottom
- This
->lockedRect
.top
)-1,
397 GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
, This
->allocatedMemory
);
398 vcheckGLcall("glDrawPixels");
403 glDrawPixels(This
->lockedRect
.right
- This
->lockedRect
.left
, (This
->lockedRect
.bottom
- This
->lockedRect
.top
)-1,
404 GL_RGB
, GL_UNSIGNED_BYTE
, This
->allocatedMemory
);
405 vcheckGLcall("glDrawPixels");
408 case D3DFMT_A8R8G8B8
:
410 glPixelStorei(GL_PACK_SWAP_BYTES
, TRUE
);
411 vcheckGLcall("glPixelStorei");
412 glDrawPixels(This
->lockedRect
.right
- This
->lockedRect
.left
, (This
->lockedRect
.bottom
- This
->lockedRect
.top
)-1,
413 GL_BGRA
, GL_UNSIGNED_BYTE
, This
->allocatedMemory
);
414 vcheckGLcall("glDrawPixels");
415 glPixelStorei(GL_PACK_SWAP_BYTES
, prev_store
);
416 vcheckGLcall("glPixelStorei");
420 FIXME("Unsupported Format %u in locking func\n", This
->currentDesc
.Format
);
423 glPixelZoom(1.0,1.0);
424 vcheckGLcall("glPixelZoom");
425 glDrawBuffer(prev_draw
);
426 vcheckGLcall("glDrawBuffer");
427 glRasterPos3iv(&prev_rasterpos
[0]);
428 vcheckGLcall("glRasterPos3iv");
430 /* Reset to previous pack row length / blending state */
431 glPixelStorei(GL_UNPACK_ROW_LENGTH
, skipBytes
);
432 if (This
->resource
.wineD3DDevice
->stateBlock
->renderState
[D3DRS_ALPHABLENDENABLE
]) glEnable(GL_BLEND
);
436 /** restore clean dirty state */
437 IWineD3DSurface_CleanDirtyRect(iface
);
440 FIXME("unsupported unlocking to Rendering surface surf@%p usage(%lu)\n", This
, This
->currentDesc
.Usage
);
443 } else if (D3DUSAGE_DEPTHSTENCIL
& This
->currentDesc
.Usage
) { /* stencil surfaces */
445 if (This
== This
->resource
.wineD3DDevice
->depthStencilBuffer
) {
446 FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This
, This
->currentDesc
.Usage
);
448 FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This
, This
->currentDesc
.Usage
);
452 FIXME("unsupported unlocking to surface surf@%p usage(%lu)\n", This
, This
->currentDesc
.Usage
);
456 This
->locked
= FALSE
;
457 memset(&This
->lockedRect
, 0, sizeof(RECT
));
461 HRESULT WINAPI
IWineD3DSurfaceImpl_GetDC(IWineD3DSurface
*iface
, HDC
*pHDC
) {
462 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
463 FIXME("No support for GetDC yet for surface %p\n", This
);
464 return D3DERR_INVALIDCALL
;
467 HRESULT WINAPI
IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface
*iface
, HDC hDC
) {
468 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
469 FIXME("No support for ReleaseDC yet for surface %p\n", This
);
470 return D3DERR_INVALIDCALL
;
473 /* ******************************************************
474 IWineD3DSurface Internal (No mapping to directx api) parts follow
475 ****************************************************** */
476 HRESULT WINAPI
IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface
*iface
, GLenum gl_target
, GLenum gl_level
) {
477 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
482 if (This
->inPBuffer
) {
486 FIXME("Surface in texture is only supported for level 0\n");
487 else if (This
->currentDesc
.Format
== D3DFMT_P8
|| This
->currentDesc
.Format
== D3DFMT_A8P8
||
488 This
->currentDesc
.Format
== D3DFMT_DXT1
|| This
->currentDesc
.Format
== D3DFMT_DXT3
||
489 This
->currentDesc
.Format
== D3DFMT_DXT5
)
490 FIXME("Format %d not supported\n", This
->currentDesc
.Format
);
492 glCopyTexImage2D(gl_target
,
494 D3DFmt2GLIntFmt(This
->resource
.wineD3DDevice
,
495 This
->currentDesc
.Format
),
498 This
->currentDesc
.Width
,
499 This
->currentDesc
.Height
,
501 TRACE("Updating target %d\n", gl_target
);
502 This
->inTexture
= TRUE
;
508 if ((This
->currentDesc
.Format
== D3DFMT_P8
|| This
->currentDesc
.Format
== D3DFMT_A8P8
) &&
509 !GL_SUPPORT(EXT_PALETTED_TEXTURE
)) {
511 * wanted a paletted texture and not really support it in HW
512 * so software emulation code begin
515 PALETTEENTRY
* pal
= This
->resource
.wineD3DDevice
->palettes
[This
->resource
.wineD3DDevice
->currentPalette
];
516 VOID
* surface
= (VOID
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->currentDesc
.Width
* This
->currentDesc
.Height
* sizeof(DWORD
));
517 BYTE
* dst
= (BYTE
*) surface
;
518 BYTE
* src
= (BYTE
*) This
->allocatedMemory
;
520 for (i
= 0; i
< This
->currentDesc
.Width
* This
->currentDesc
.Height
; i
++) {
522 *dst
++ = pal
[color
].peRed
;
523 *dst
++ = pal
[color
].peGreen
;
524 *dst
++ = pal
[color
].peBlue
;
525 if (This
->currentDesc
.Format
== D3DFMT_A8P8
)
526 *dst
++ = pal
[color
].peFlags
;
533 TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
537 This
->currentDesc
.Width
,
538 This
->currentDesc
.Height
,
543 glTexImage2D(gl_target
,
546 This
->currentDesc
.Width
,
547 This
->currentDesc
.Height
,
552 checkGLcall("glTexImage2D");
553 HeapFree(GetProcessHeap(), 0, surface
);
560 if (This
->currentDesc
.Format
== D3DFMT_DXT1
||
561 This
->currentDesc
.Format
== D3DFMT_DXT3
||
562 This
->currentDesc
.Format
== D3DFMT_DXT5
) {
563 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
564 TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
567 D3DFmt2GLIntFmt(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
),
568 This
->currentDesc
.Width
,
569 This
->currentDesc
.Height
,
571 This
->currentDesc
.Size
,
572 This
->allocatedMemory
);
576 GL_EXTCALL(glCompressedTexImage2DARB
)(gl_target
,
578 D3DFmt2GLIntFmt(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
),
579 This
->currentDesc
.Width
,
580 This
->currentDesc
.Height
,
582 This
->currentDesc
.Size
,
583 This
->allocatedMemory
);
584 checkGLcall("glCommpressedTexTexImage2D");
588 FIXME("Using DXT1/3/5 without advertized support\n");
592 TRACE("Calling glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
595 debug_d3dformat(This
->currentDesc
.Format
),
596 D3DFmt2GLIntFmt(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
),
597 This
->currentDesc
.Width
,
598 This
->currentDesc
.Height
,
600 D3DFmt2GLFmt(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
),
601 D3DFmt2GLType(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
),
602 This
->allocatedMemory
);
606 glTexImage2D(gl_target
,
608 D3DFmt2GLIntFmt(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
),
609 This
->currentDesc
.Width
,
610 This
->currentDesc
.Height
,
612 D3DFmt2GLFmt(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
),
613 D3DFmt2GLType(This
->resource
.wineD3DDevice
, This
->currentDesc
.Format
),
614 This
->allocatedMemory
);
615 checkGLcall("glTexImage2D");
621 static unsigned int gen
= 0;
624 if ((gen
% 10) == 0) {
625 snprintf(buffer
, sizeof(buffer
), "/tmp/surface%p_type%u_level%u_%u.ppm", This
, gl_target
, gl_level
, gen
);
626 IWineD3DSurfaceImpl_SaveSnapshot((LPDIRECT3DSURFACE8
) This
, buffer
);
629 * debugging crash code
644 HRESULT WINAPI
IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface
*iface
, const char* filename
) {
647 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
649 f
= fopen(filename
, "w+");
651 ERR("opening of %s failed with: %s\n", filename
, strerror(errno
));
652 return D3DERR_INVALIDCALL
;
655 TRACE("opened %s with format %s\n", filename
, debug_d3dformat(This
->currentDesc
.Format
));
657 fprintf(f
, "P6\n%u %u\n255\n", This
->currentDesc
.Width
, This
->currentDesc
.Height
);
658 switch (This
->currentDesc
.Format
) {
659 case D3DFMT_X8R8G8B8
:
660 case D3DFMT_A8R8G8B8
:
663 for (i
= 0; i
< This
->currentDesc
.Width
* This
->currentDesc
.Height
; i
++) {
664 color
= ((DWORD
*) This
->allocatedMemory
)[i
];
665 fputc((color
>> 16) & 0xFF, f
);
666 fputc((color
>> 8) & 0xFF, f
);
667 fputc((color
>> 0) & 0xFF, f
);
674 for (i
= 0; i
< This
->currentDesc
.Width
* This
->currentDesc
.Height
; i
++) {
675 color
= ((BYTE
*) This
->allocatedMemory
) + (3 * i
);
676 fputc((color
[0]) & 0xFF, f
);
677 fputc((color
[1]) & 0xFF, f
);
678 fputc((color
[2]) & 0xFF, f
);
682 case D3DFMT_A1R5G5B5
:
685 for (i
= 0; i
< This
->currentDesc
.Width
* This
->currentDesc
.Height
; i
++) {
686 color
= ((WORD
*) This
->allocatedMemory
)[i
];
687 fputc(((color
>> 10) & 0x1F) * 255 / 31, f
);
688 fputc(((color
>> 5) & 0x1F) * 255 / 31, f
);
689 fputc(((color
>> 0) & 0x1F) * 255 / 31, f
);
693 case D3DFMT_A4R4G4B4
:
696 for (i
= 0; i
< This
->currentDesc
.Width
* This
->currentDesc
.Height
; i
++) {
697 color
= ((WORD
*) This
->allocatedMemory
)[i
];
698 fputc(((color
>> 8) & 0x0F) * 255 / 15, f
);
699 fputc(((color
>> 4) & 0x0F) * 255 / 15, f
);
700 fputc(((color
>> 0) & 0x0F) * 255 / 15, f
);
708 for (i
= 0; i
< This
->currentDesc
.Width
* This
->currentDesc
.Height
; i
++) {
709 color
= ((WORD
*) This
->allocatedMemory
)[i
];
710 fputc(((color
>> 11) & 0x1F) * 255 / 31, f
);
711 fputc(((color
>> 5) & 0x3F) * 255 / 63, f
);
712 fputc(((color
>> 0) & 0x1F) * 255 / 31, f
);
717 FIXME("Unimplemented dump mode format(%u,%s)\n", This
->currentDesc
.Format
, debug_d3dformat(This
->currentDesc
.Format
));
723 HRESULT WINAPI
IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface
*iface
) {
724 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
726 This
->dirtyRect
.left
= This
->currentDesc
.Width
;
727 This
->dirtyRect
.top
= This
->currentDesc
.Height
;
728 This
->dirtyRect
.right
= 0;
729 This
->dirtyRect
.bottom
= 0;
734 * Slightly inefficient way to handle multiple dirty rects but it works :)
736 extern HRESULT WINAPI
IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface
*iface
, CONST RECT
* pDirtyRect
) {
737 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
739 if (NULL
!= pDirtyRect
) {
740 This
->dirtyRect
.left
= min(This
->dirtyRect
.left
, pDirtyRect
->left
);
741 This
->dirtyRect
.top
= min(This
->dirtyRect
.top
, pDirtyRect
->top
);
742 This
->dirtyRect
.right
= max(This
->dirtyRect
.right
, pDirtyRect
->right
);
743 This
->dirtyRect
.bottom
= max(This
->dirtyRect
.bottom
, pDirtyRect
->bottom
);
745 This
->dirtyRect
.left
= 0;
746 This
->dirtyRect
.top
= 0;
747 This
->dirtyRect
.right
= This
->currentDesc
.Width
;
748 This
->dirtyRect
.bottom
= This
->currentDesc
.Height
;
753 IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl
=
755 IWineD3DSurfaceImpl_QueryInterface
,
756 IWineD3DSurfaceImpl_AddRef
,
757 IWineD3DSurfaceImpl_Release
,
758 IWineD3DSurfaceImpl_GetParent
,
759 IWineD3DSurfaceImpl_GetDevice
,
760 IWineD3DSurfaceImpl_SetPrivateData
,
761 IWineD3DSurfaceImpl_GetPrivateData
,
762 IWineD3DSurfaceImpl_FreePrivateData
,
763 IWineD3DSurfaceImpl_SetPriority
,
764 IWineD3DSurfaceImpl_GetPriority
,
765 IWineD3DSurfaceImpl_PreLoad
,
766 IWineD3DSurfaceImpl_GetType
,
767 IWineD3DSurfaceImpl_GetContainer
,
768 IWineD3DSurfaceImpl_GetDesc
,
769 IWineD3DSurfaceImpl_LockRect
,
770 IWineD3DSurfaceImpl_UnlockRect
,
771 IWineD3DSurfaceImpl_GetDC
,
772 IWineD3DSurfaceImpl_ReleaseDC
,
774 IWineD3DSurfaceImpl_CleanDirtyRect
,
775 IWineD3DSurfaceImpl_AddDirtyRect
,
776 IWineD3DSurfaceImpl_LoadTexture
,
777 IWineD3DSurfaceImpl_SaveSnapshot