2 * IWineD3DSurface Implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/port.h"
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
31 /* *******************************************
32 IWineD3DSurface IUnknown parts follow
33 ******************************************* */
34 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
36 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
37 /* Warn ,but be nice about things */
38 TRACE("(%p)->(%s,%p) \n", This,debugstr_guid(riid),ppobj);
40 ERR("Probably FIXME: Calling query interface with NULL riid\n");
42 if (IsEqualGUID(riid, &IID_IUnknown)
43 || IsEqualGUID(riid, &IID_IWineD3DResource)
44 || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
45 IUnknown_AddRef((IUnknown*)iface);
52 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
53 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
54 ULONG ref = InterlockedIncrement(&This->resource.ref);
55 TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
59 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
60 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
61 ULONG ref = InterlockedDecrement(&This->resource.ref);
62 TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
64 TRACE("(%p) : cleaning up\n", This);
65 if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
67 TRACE("Deleting texture %d\n", This->glDescription.textureName);
68 glDeleteTextures(1, &This->glDescription.textureName);
71 IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
73 TRACE("(%p) Released\n", This);
74 HeapFree(GetProcessHeap(), 0, This);
80 /* ****************************************************
81 IWineD3DSurface IWineD3DResource parts follow
82 **************************************************** */
83 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
84 return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
87 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
88 return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
91 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
92 return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
95 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
96 return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
99 DWORD WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
100 return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
103 DWORD WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
104 return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
107 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
108 /* TODO: re-write the way textures and managed,
109 * use a 'opengl context manager' to manage RenderTarget surfaces
110 ** *********************************************************/
112 /* TODO: check for locks */
113 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
114 IWineD3DBaseTexture *baseTexture = NULL;
115 TRACE("(%p)Checking to see if the container is a base texture\n", This);
116 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == D3D_OK) {
117 TRACE("Passing to conatiner\n");
118 IWineD3DBaseTexture_PreLoad(baseTexture);
119 IWineD3DBaseTexture_Release(baseTexture);
121 TRACE("(%p) : About to load surface\n", This);
123 #if 0 /* TODO: context manager support */
124 IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
126 glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
127 if (This->glDescription.level == 0 && This->glDescription.textureName == 0) {
128 glGenTextures(1, &This->glDescription.textureName);
129 checkGLcall("glGenTextures");
130 TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
131 glBindTexture(This->glDescription.target, This->glDescription.textureName);
132 checkGLcall("glBindTexture");
133 IWineD3DSurface_LoadTexture(iface);
134 /* This is where we should be reducing the amount of GLMemoryUsed */
136 if (This->glDescription.level == 0) {
137 glBindTexture(This->glDescription.target, This->glDescription.textureName);
138 checkGLcall("glBindTexture");
139 IWineD3DSurface_LoadTexture(iface);
140 } else if (This->glDescription.textureName != 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
141 /* assume this is a coding error not a real error for now */
142 FIXME("Mipmap surface has a glTexture bound to it!\n");
145 if (This->resource.pool == D3DPOOL_DEFAULT) {
146 /* Tell opengl to try and keep this texture in video ram (well mostly) */
149 glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
151 /* TODO: disable texture support, if it wastn't enabled when we entered. */
152 #if 0 /* TODO: context manager support */
153 IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
154 /* we don't care when the state is disabled(if atall) */);
161 D3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
162 TRACE("(%p) : calling resourceimpl_GetType\n", iface);
163 return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
166 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
167 TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
168 return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
171 /* ******************************************************
172 IWineD3DSurface IWineD3DSurface parts follow
173 ****************************************************** */
175 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
176 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
178 if (ppContainer == NULL) {
179 ERR("Get container called witout a null ppContainer\n");
180 return E_NOINTERFACE;
182 TRACE("(%p) : Relaying to queryInterface %p %p\n", This, ppContainer, *ppContainer);
184 * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
185 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
186 * GetContainer will return the Direct3D device used to create the surface.
188 hr = IUnknown_QueryInterface(This->container, riid, ppContainer);
192 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
193 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
195 TRACE("(%p) : copying into %p\n", This, pDesc);
196 if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format;
197 if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType;
198 if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage;
199 if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool;
200 if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */
201 if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType;
202 if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
203 if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width;
204 if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height;
208 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
209 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
210 TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
211 if (This->glDescription.textureName == 0 && textureName != 0) {
213 IWineD3DSurface_AddDirtyRect(iface, NULL);
215 This->glDescription.textureName = textureName;
216 This->glDescription.target = target;
219 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
220 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
221 TRACE("(%p) : returning %p\n", This, &This->glDescription);
222 *glDescription = &This->glDescription;
225 /* TODO: think about moving this down to resource? */
226 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
227 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
228 /* This should only be called for sysmem textures, it may be a good idea to extend this to all pools at some point in the futture */
229 if (This->resource.pool != D3DPOOL_SYSTEMMEM) {
230 FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
232 return (CONST void*)(This->resource.allocatedMemory);
235 HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
236 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
237 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
238 IWineD3DSwapChainImpl *swapchain = NULL;
239 static UINT messages = 0; /* holds flags to disable fixme messages */
241 /* fixme: should we really lock as such? */
242 if (This->inTexture && This->inPBuffer) {
243 FIXME("Warning: Surface is in texture memory or pbuffer\n");
248 if (FALSE == This->lockable) {
249 /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
250 texture regions, and since the destination is an unlockable region we need
252 TRACE("Warning: trying to lock unlockable surf@%p\n", This);
253 /*return D3DERR_INVALIDCALL; */
256 if (This->resource.usage & D3DUSAGE_RENDERTARGET) {
257 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
259 if (swapchain != NULL || iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
260 if (swapchain != NULL && iface == swapchain->backBuffer) {
261 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
262 } else if (swapchain != NULL && iface == swapchain->frontBuffer) {
263 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
264 } else if (iface == myDevice->renderTarget) {
265 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
266 } else if (iface == myDevice->depthStencilBuffer) {
267 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
270 if (NULL != swapchain) {
271 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
276 TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
279 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
280 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt3/5)
281 ie pitch = (width/4) * bytes per block */
282 if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
283 pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 3;
284 else if (This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT5) /* DXT3/5 is 16 bytes per block */
285 pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 4;
287 pLockedRect->Pitch = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
290 pLockedRect->pBits = This->resource.allocatedMemory;
291 This->lockedRect.left = 0;
292 This->lockedRect.top = 0;
293 This->lockedRect.right = This->currentDesc.Width;
294 This->lockedRect.bottom = This->currentDesc.Height;
295 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);
297 TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
299 if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
300 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel/2));
302 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
304 This->lockedRect.left = pRect->left;
305 This->lockedRect.top = pRect->top;
306 This->lockedRect.right = pRect->right;
307 This->lockedRect.bottom = pRect->bottom;
311 TRACE("Locking non-power 2 texture\n");
314 if (0 == This->resource.usage || This->resource.usage & D3DUSAGE_DYNAMIC) {
315 /* classic surface TODO: non 2d surfaces?
316 Thease resources may be POOL_SYSTEMMEM, so they must not access the device */
317 TRACE("locking an ordinarary surface\n");
318 /* Check to see if memory has already been allocated fro the sufrace*/
319 if (NULL == This->resource.allocatedMemory) { /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
320 /* Non-systemmemory surfaces */
322 /*Surface has no memory currently allocate to it!*/
323 TRACE("(%p) Locking rect\n" , This);
324 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
326 /*Now I have to copy thing bits back*/
327 This->activeLock = TRUE; /* When this flag is set to true, laoding the surface again won't free THis->resource.allocatedMemory */
328 /* TODO: make activeLock a bit more intelegent, maybe implement a method to purge the texture memory. */
331 /* Make sure that the texture is loaded */
332 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
334 TRACE("(%p) glGetTexImage level(%d), fmt(%d), typ(%d), mem(%p) \n" , This, This->glDescription.level, This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
335 /* TODO: DXT2 and DXT4 formats */
336 if (This->resource.format == WINED3DFMT_DXT1 ||
337 This->resource.format == WINED3DFMT_DXT3 ||
338 This->resource.format == WINED3DFMT_DXT5) {
339 TRACE("Locking a compressed texture\n");
340 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* we can assume this as the texture would not have been created otherwise */
341 GL_EXTCALL(glGetCompressedTexImageARB)(This->glDescription.target,
342 This->glDescription.level,
343 This->resource.allocatedMemory);
346 FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
349 glGetTexImage(This->glDescription.target,
350 This->glDescription.level,
351 This->glDescription.glFormat,
352 This->glDescription.glType,
353 This->resource.allocatedMemory);
354 vcheckGLcall("glGetTexImage");
357 } else { /* Nothing to do */
358 TRACE("Memory %p already allocted for texture\n", This->resource.allocatedMemory);
362 pLockedRect->pBits = This->resource.allocatedMemory;
364 if (This->resource.format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
365 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel/2));
367 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
371 } else if (D3DUSAGE_RENDERTARGET & This->resource.usage && !(Flags&D3DLOCK_DISCARD)) { /* render surfaces */
375 BOOL notInContext = FALSE;
376 IWineD3DSwapChainImpl *targetSwapChain = NULL;
382 * for render->surface copy begin to begin of allocatedMemory
383 * unlock can be more easy
386 TRACE("locking a render target\n");
388 if (This->resource.allocatedMemory == NULL)
389 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
391 This->activeLock = TRUE; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
392 pLockedRect->pBits = This->resource.allocatedMemory;
395 vcheckGLcall("glFlush");
396 glGetIntegerv(GL_READ_BUFFER, &prev_read);
397 vcheckGLcall("glIntegerv");
398 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
399 vcheckGLcall("glIntegerv");
401 /* Here's what we have to do:
402 See if the swapchain has the same context as the renderTarget or the surface is the render target.
403 Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
404 and use the front back buffer as required.
405 if not, we need to switch contexts and then switchback at the end.
407 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
408 IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
410 /* NOTE: In a shared context environment the renderTarget will use the same context as the implicit swapchain (we're not in a shared environment yet! */
411 if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
412 if (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
413 TRACE("locking back buffer\n");
414 glReadBuffer(GL_BACK);
415 } else if (iface == swapchain->frontBuffer) {
416 TRACE("locking front\n");
417 glReadBuffer(GL_FRONT);
418 } else if (iface == myDevice->depthStencilBuffer) {
419 FIXME("Stencil Buffer lock unsupported for now\n");
421 FIXME("(%p) Shouldn't have got here!\n", This);
422 glReadBuffer(GL_BACK);
424 } else if (swapchain != NULL) {
425 IWineD3DSwapChainImpl *implSwapChain;
426 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
427 if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
428 /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
429 if (iface == swapchain->backBuffer) {
430 glReadBuffer(GL_BACK);
431 } else if (iface == swapchain->frontBuffer) {
432 glReadBuffer(GL_FRONT);
433 } else if (iface == myDevice->depthStencilBuffer) {
434 FIXME("Stencil Buffer lock unsupported for now\n");
436 FIXME("Should have got here!\n");
437 glReadBuffer(GL_BACK);
440 /* We need to switch contexts to be able to read the buffer!!! */
441 FIXME("The buffer requested isn't in the current openGL context\n");
443 /* TODO: check the contexts, to see if were shared with the current context */
445 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
447 if (swapchain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
448 if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
451 /** the depth stencil in openGL has a format of GL_FLOAT
452 * which should be good for WINED3DFMT_D16_LOCKABLE
454 * it is unclear what format the stencil buffer is in except.
455 * 'Each index is converted to fixed point...
456 * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
457 * mappings in the table GL_PIXEL_MAP_S_TO_S.
458 * glReadPixels(This->lockedRect.left,
459 * This->lockedRect.bottom - j - 1,
460 * This->lockedRect.right - This->lockedRect.left,
462 * GL_DEPTH_COMPONENT,
464 * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
465 *****************************************/
466 if (!notInContext) { /* Only read the buffer if it's in the current context */
469 /* Bizarly it takes 120 millseconds to get an 800x600 region a line at a time, but only 10 to get the whole lot every time,
470 * This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
471 * run ten times faster!
472 * ************************************/
473 BOOL ati_performance_hack = FALSE;
474 ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
476 if ((This->lockedRect.left == 0 && This->lockedRect.top == 0 &&
477 This->lockedRect.right == This->currentDesc.Width
478 && This->lockedRect.bottom == This->currentDesc.Height)) {
480 This->currentDesc.Width,
481 This->currentDesc.Height,
482 This->glDescription.glFormat,
483 This->glDescription.glType,
484 (char *)pLockedRect->pBits);
485 } else if (This->lockedRect.left == 0 && This->lockedRect.right == This->currentDesc.Width) {
487 This->lockedRect.top,
488 This->currentDesc.Width,
489 This->currentDesc.Height,
490 This->glDescription.glFormat,
491 This->glDescription.glType,
492 (char *)pLockedRect->pBits);
495 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
496 glReadPixels(This->lockedRect.left,
497 This->lockedRect.bottom - j - 1,
498 This->lockedRect.right - This->lockedRect.left,
500 This->glDescription.glFormat,
501 This->glDescription.glType,
502 (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
506 vcheckGLcall("glReadPixels");
507 TRACE("Resetting buffer\n");
508 glReadBuffer(prev_read);
509 vcheckGLcall("glReadBuffer");
513 } else if (D3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
516 FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This, This->resource.usage);
519 glReadPixels(This->lockedRect.left,
520 This->lockedRect.bottom - j - 1,
521 This->lockedRect.right - This->lockedRect.left,
523 GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
530 FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
533 if (Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY)) {
536 IWineD3DBaseTexture *pBaseTexture;
539 * as seen in msdn docs
541 IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
543 /** Dirtify Container if needed */
544 if (D3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
545 TRACE("Making container dirty\n");
546 IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
547 IWineD3DBaseTexture_Release(pBaseTexture);
549 TRACE("Surface is standalone, no need to dirty the container\n");
553 TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Dirty);
559 HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
561 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
562 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
563 const char *buffername = "";
564 IWineD3DSwapChainImpl *swapchain = NULL;
566 if (FALSE == This->locked) {
567 WARN("trying to Unlock an unlocked surf@%p\n", This);
568 return D3DERR_INVALIDCALL;
571 if (D3DUSAGE_RENDERTARGET & This->resource.usage) {
572 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
574 if ((swapchain != NULL) && iface == swapchain->backBuffer) {
575 buffername = "backBuffer";
576 } else if ((swapchain != NULL) && iface == swapchain->frontBuffer) {
577 buffername = "frontBuffer";
578 } else if (iface == myDevice->depthStencilBuffer) {
579 buffername = "depthStencilBuffer";
580 } else if (iface == myDevice->renderTarget) {
581 buffername = "renderTarget";
585 if (swapchain != NULL) {
586 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
589 TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Dirty);
591 if (FALSE == This->Dirty) {
592 TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
596 if (0 == This->resource.usage) { /* classic surface */
599 * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
601 } else if (D3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
603 /****************************
604 * TODO: Render targets are 'special' and
605 * ?some? locking needs to be passed onto the context manager
606 * so that it becomes possible to use auxilary buffers, pbuffers
607 * render-to-texture, shared, cached contexts etc...
608 * ****************************/
609 IWineD3DSwapChainImpl *implSwapChain;
610 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
612 if (iface == implSwapChain->backBuffer || iface == implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
615 GLint prev_rasterpos[4];
620 vcheckGLcall("glFlush");
621 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
622 vcheckGLcall("glIntegerv");
623 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
624 vcheckGLcall("glIntegerv");
625 glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
626 vcheckGLcall("glIntegerv");
627 glPixelZoom(1.0, -1.0);
628 vcheckGLcall("glPixelZoom");
630 /* glDrawPixels transforms the raster position as though it was a vertex -
631 we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
632 per drawprim (and leave set - it will sort itself out due to last_was_rhw */
633 if (!myDevice->last_was_rhw) {
635 double X, Y, height, width, minZ, maxZ;
636 myDevice->last_was_rhw = TRUE;
638 /* Transformed already into viewport coordinates, so we do not need transform
639 matrices. Reset all matrices to identity and leave the default matrix in world
641 glMatrixMode(GL_MODELVIEW);
642 checkGLcall("glMatrixMode");
644 checkGLcall("glLoadIdentity");
646 glMatrixMode(GL_PROJECTION);
647 checkGLcall("glMatrixMode");
649 checkGLcall("glLoadIdentity");
651 /* Set up the viewport to be full viewport */
652 X = myDevice->stateBlock->viewport.X;
653 Y = myDevice->stateBlock->viewport.Y;
654 height = myDevice->stateBlock->viewport.Height;
655 width = myDevice->stateBlock->viewport.Width;
656 minZ = myDevice->stateBlock->viewport.MinZ;
657 maxZ = myDevice->stateBlock->viewport.MaxZ;
658 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
659 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
660 checkGLcall("glOrtho");
662 /* Window Coord 0 is the middle of the first pixel, so translate by half
663 a pixel (See comment above glTranslate below) */
664 glTranslatef(0.5, 0.5, 0);
665 checkGLcall("glTranslatef(0.5, 0.5, 0)");
668 if (iface == implSwapChain->backBuffer || iface == myDevice->renderTarget) {
669 glDrawBuffer(GL_BACK);
670 } else if (iface == implSwapChain->frontBuffer) {
671 glDrawBuffer(GL_FRONT);
674 vcheckGLcall("glDrawBuffer");
676 /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
677 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
678 glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
680 /* And back buffers are not blended */
683 glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
684 vcheckGLcall("glRasterPos2f");
685 switch (This->resource.format) {
686 case WINED3DFMT_R5G6B5:
688 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
689 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->resource.allocatedMemory);
690 vcheckGLcall("glDrawPixels");
693 case WINED3DFMT_R8G8B8:
695 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
696 GL_RGB, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
697 vcheckGLcall("glDrawPixels");
700 case WINED3DFMT_X8R8G8B8: /* make sure the X byte is set to alpha on, since it
701 could be any random value this fixes the intro move in Pirates! */
705 data = (unsigned int *)This->resource.allocatedMemory;
706 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
713 case WINED3DFMT_A8R8G8B8:
715 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
716 vcheckGLcall("glPixelStorei");
717 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
718 GL_BGRA, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
719 vcheckGLcall("glDrawPixels");
720 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
721 vcheckGLcall("glPixelStorei");
725 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
728 glPixelZoom(1.0,1.0);
729 vcheckGLcall("glPixelZoom");
730 glDrawBuffer(prev_draw);
731 vcheckGLcall("glDrawBuffer");
732 glRasterPos3iv(&prev_rasterpos[0]);
733 vcheckGLcall("glRasterPos3iv");
735 /* Reset to previous pack row length / blending state */
736 glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
737 if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
741 /** restore clean dirty state */
742 IWineD3DSurface_CleanDirtyRect(iface);
745 FIXME("unsupported unlocking to Rendering surface surf@%p usage(%lu)\n", This, This->resource.usage);
747 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
749 } else if (D3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
751 if (iface == myDevice->depthStencilBuffer) {
752 FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
754 FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
758 FIXME("unsupported unlocking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
762 This->locked = FALSE;
763 memset(&This->lockedRect, 0, sizeof(RECT));
767 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
768 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
769 FIXME("No support for GetDC yet for surface %p\n", This);
770 return D3DERR_INVALIDCALL;
773 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
774 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
775 FIXME("No support for ReleaseDC yet for surface %p\n", This);
776 return D3DERR_INVALIDCALL;
779 /* ******************************************************
780 IWineD3DSurface Internal (No mapping to directx api) parts follow
781 ****************************************************** */
782 HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
783 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
785 if (This->inTexture) {
786 TRACE("Surface already in texture\n");
789 if (This->Dirty == FALSE) {
790 TRACE("surface isn't dirty\n");
796 /* Resources are placed in system RAM and do not need to be recreated when a device is lost. These resources are not bound by device size or format restrictions. Because of this, these resources cannot be accessed by the Direct3D device nor set as textures or render targets. However, these resources can always be created, locked, and copied. */
797 if (This->resource.pool == D3DPOOL_SCRATCH || This->resource.pool == D3DPOOL_SYSTEMMEM) /*never store scratch or system mem textures in the video ram*/
799 FIXME("(%p) Opperation not supported for scratch or SYSTEMMEM textures\n",This);
800 return D3DERR_INVALIDCALL;
803 if (This->inPBuffer) {
806 if (This->glDescription.level != 0)
807 FIXME("Surface in texture is only supported for level 0\n");
808 else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
809 This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT3 ||
810 This->resource.format == WINED3DFMT_DXT5)
811 FIXME("Format %d not supported\n", This->resource.format);
814 glGetIntegerv(GL_READ_BUFFER, &prevRead);
815 vcheckGLcall("glGetIntegerv");
816 glReadBuffer(GL_BACK);
817 vcheckGLcall("glReadBuffer");
819 glCopyTexImage2D(This->glDescription.target,
820 This->glDescription.level,
821 This->glDescription.glFormatInternal,
824 This->currentDesc.Width,
825 This->currentDesc.Height,
828 checkGLcall("glCopyTexImage2D");
829 glReadBuffer(prevRead);
830 vcheckGLcall("glReadBuffer");
831 TRACE("Updating target %d\n", This->glDescription.target);
832 This->inTexture = TRUE;
838 if ((This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) &&
839 !GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
841 * wanted a paletted texture and not really support it in HW
842 * so software emulation code begin
845 PALETTEENTRY* pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
846 VOID* surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->currentDesc.Width * This->currentDesc.Height * sizeof(DWORD));
847 BYTE* dst = (BYTE*) surface;
848 BYTE* src = (BYTE*) This->resource.allocatedMemory;
850 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
852 *dst++ = pal[color].peRed;
853 *dst++ = pal[color].peGreen;
854 *dst++ = pal[color].peBlue;
855 if (This->resource.format == WINED3DFMT_A8P8)
856 *dst++ = pal[color].peFlags;
863 TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
864 This->glDescription.target,
865 This->glDescription.level,
867 This->currentDesc.Width,
868 This->currentDesc.Height,
873 glTexImage2D(This->glDescription.target,
874 This->glDescription.level,
876 This->currentDesc.Width,
877 This->currentDesc.Height,
882 checkGLcall("glTexImage2D");
883 HeapFree(GetProcessHeap(), 0, surface);
890 /* TODO: Compressed non-power 2 support */
891 /* TODO: DXT2 DXT4 support */
892 if (This->resource.format == WINED3DFMT_DXT1 ||
893 This->resource.format == WINED3DFMT_DXT3 ||
894 This->resource.format == WINED3DFMT_DXT5) {
895 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
896 TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
897 This->glDescription.target,
898 This->glDescription.level,
899 This->glDescription.glFormatInternal,
900 This->currentDesc.Width,
901 This->currentDesc.Height,
904 This->resource.allocatedMemory);
908 GL_EXTCALL(glCompressedTexImage2DARB)(This->glDescription.target,
909 This->glDescription.level,
910 This->glDescription.glFormatInternal,
911 This->currentDesc.Width,
912 This->currentDesc.Height,
915 This->resource.allocatedMemory);
916 checkGLcall("glCommpressedTexTexImage2D");
920 if(This->activeLock == FALSE){
921 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
922 This->resource.allocatedMemory = NULL;
926 FIXME("Using DXT1/3/5 without advertized support\n");
930 /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
931 if (This->nonpow2 == TRUE) {
933 TRACE("non power of two support\n");
935 TRACE("(%p) Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n", This,
936 This->glDescription.target,
937 This->glDescription.level,
938 debug_d3dformat(This->resource.format),
939 This->glDescription.glFormatInternal,
943 This->glDescription.glFormat,
944 This->glDescription.glType,
947 glTexImage2D(This->glDescription.target,
948 This->glDescription.level,
949 This->glDescription.glFormatInternal,
953 This->glDescription.glFormat,
954 This->glDescription.glType,
957 checkGLcall("glTexImage2D");
958 if (This->resource.allocatedMemory != NULL) {
959 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory);
960 /* And map the non-power two data into the top left corner */
962 This->glDescription.target,
963 This->glDescription.level,
966 This->currentDesc.Width,
967 This->currentDesc.Height,
968 This->glDescription.glFormat,
969 This->glDescription.glType,
970 This->resource.allocatedMemory
972 checkGLcall("glTexSubImage2D");
978 TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
979 This->glDescription.target,
980 This->glDescription.level,
981 debug_d3dformat(This->resource.format),
982 This->glDescription.glFormatInternal,
983 This->currentDesc.Width,
984 This->currentDesc.Height,
986 This->glDescription.glFormat,
987 This->glDescription.glType,
988 This->resource.allocatedMemory);
991 glTexImage2D(This->glDescription.target,
992 This->glDescription.level,
993 This->glDescription.glFormatInternal,
994 This->currentDesc.Width,
995 This->currentDesc.Height,
997 This->glDescription.glFormat,
998 This->glDescription.glType,
999 This->resource.allocatedMemory);
1000 checkGLcall("glTexImage2D");
1006 static unsigned int gen = 0;
1009 if ((gen % 10) == 0) {
1010 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1011 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1014 * debugging crash code
1022 if(This->activeLock == FALSE){
1023 HeapFree(GetProcessHeap(),0,This->resource.allocatedMemory);
1024 This->resource.allocatedMemory = NULL;
1034 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1037 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1039 f = fopen(filename, "w+");
1041 ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1042 return D3DERR_INVALIDCALL;
1045 TRACE("opened %s with format %s\n", filename, debug_d3dformat(This->resource.format));
1047 fprintf(f, "P6\n%u %u\n255\n", This->currentDesc.Width, This->currentDesc.Height);
1048 switch (This->resource.format) {
1049 case WINED3DFMT_X8R8G8B8:
1050 case WINED3DFMT_A8R8G8B8:
1053 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1054 color = ((DWORD*) This->resource.allocatedMemory)[i];
1055 fputc((color >> 16) & 0xFF, f);
1056 fputc((color >> 8) & 0xFF, f);
1057 fputc((color >> 0) & 0xFF, f);
1061 case WINED3DFMT_R8G8B8:
1064 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1065 color = ((BYTE*) This->resource.allocatedMemory) + (3 * i);
1066 fputc((color[0]) & 0xFF, f);
1067 fputc((color[1]) & 0xFF, f);
1068 fputc((color[2]) & 0xFF, f);
1072 case WINED3DFMT_A1R5G5B5:
1075 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1076 color = ((WORD*) This->resource.allocatedMemory)[i];
1077 fputc(((color >> 10) & 0x1F) * 255 / 31, f);
1078 fputc(((color >> 5) & 0x1F) * 255 / 31, f);
1079 fputc(((color >> 0) & 0x1F) * 255 / 31, f);
1083 case WINED3DFMT_A4R4G4B4:
1086 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1087 color = ((WORD*) This->resource.allocatedMemory)[i];
1088 fputc(((color >> 8) & 0x0F) * 255 / 15, f);
1089 fputc(((color >> 4) & 0x0F) * 255 / 15, f);
1090 fputc(((color >> 0) & 0x0F) * 255 / 15, f);
1095 case WINED3DFMT_R5G6B5:
1098 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1099 color = ((WORD*) This->resource.allocatedMemory)[i];
1100 fputc(((color >> 11) & 0x1F) * 255 / 31, f);
1101 fputc(((color >> 5) & 0x3F) * 255 / 63, f);
1102 fputc(((color >> 0) & 0x1F) * 255 / 31, f);
1107 FIXME("Unimplemented dump mode format(%u,%s)\n", This->resource.format, debug_d3dformat(This->resource.format));
1113 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1114 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1115 This->Dirty = FALSE;
1116 This->dirtyRect.left = This->currentDesc.Width;
1117 This->dirtyRect.top = This->currentDesc.Height;
1118 This->dirtyRect.right = 0;
1119 This->dirtyRect.bottom = 0;
1120 TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left,
1121 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1126 * Slightly inefficient way to handle multiple dirty rects but it works :)
1128 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1129 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1130 IWineD3DBaseTexture *baseTexture = NULL;
1132 if (NULL != pDirtyRect) {
1133 This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left);
1134 This->dirtyRect.top = min(This->dirtyRect.top, pDirtyRect->top);
1135 This->dirtyRect.right = max(This->dirtyRect.right, pDirtyRect->right);
1136 This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1138 This->dirtyRect.left = 0;
1139 This->dirtyRect.top = 0;
1140 This->dirtyRect.right = This->currentDesc.Width;
1141 This->dirtyRect.bottom = This->currentDesc.Height;
1143 TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left,
1144 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1145 /* if the container is a basetexture then mark it dirty. */
1146 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == D3D_OK) {
1147 TRACE("Passing to conatiner\n");
1148 IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1149 IWineD3DBaseTexture_Release(baseTexture);
1154 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IUnknown *container) {
1155 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1156 TRACE("Setting container to %p from %p\n", container, This->container);
1157 This->container = container;
1161 /* TODO: replace this function with context management routines */
1162 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL inTexture) {
1163 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1165 This->inPBuffer = inPBuffer;
1166 This->inTexture = inTexture;
1170 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
1173 IWineD3DSurfaceImpl_QueryInterface,
1174 IWineD3DSurfaceImpl_AddRef,
1175 IWineD3DSurfaceImpl_Release,
1176 /* IWineD3DResource */
1177 IWineD3DSurfaceImpl_GetParent,
1178 IWineD3DSurfaceImpl_GetDevice,
1179 IWineD3DSurfaceImpl_SetPrivateData,
1180 IWineD3DSurfaceImpl_GetPrivateData,
1181 IWineD3DSurfaceImpl_FreePrivateData,
1182 IWineD3DSurfaceImpl_SetPriority,
1183 IWineD3DSurfaceImpl_GetPriority,
1184 IWineD3DSurfaceImpl_PreLoad,
1185 IWineD3DSurfaceImpl_GetType,
1186 /* IWineD3DSurface */
1187 IWineD3DSurfaceImpl_GetContainer,
1188 IWineD3DSurfaceImpl_GetDesc,
1189 IWineD3DSurfaceImpl_LockRect,
1190 IWineD3DSurfaceImpl_UnlockRect,
1191 IWineD3DSurfaceImpl_GetDC,
1192 IWineD3DSurfaceImpl_ReleaseDC,
1194 IWineD3DSurfaceImpl_CleanDirtyRect,
1195 IWineD3DSurfaceImpl_AddDirtyRect,
1196 IWineD3DSurfaceImpl_LoadTexture,
1197 IWineD3DSurfaceImpl_SaveSnapshot,
1198 IWineD3DSurfaceImpl_SetContainer,
1199 IWineD3DSurfaceImpl_SetPBufferState,
1200 IWineD3DSurfaceImpl_SetGlTextureDesc,
1201 IWineD3DSurfaceImpl_GetGlDesc,
1202 IWineD3DSurfaceImpl_GetData