Removed some more uses of the non-standard ICOM_THIS macro.
[wine/multimedia.git] / dlls / d3d8 / surface.c
blob7a098df080880324a19fdb7760148999e0fe4b8c
1 /*
2 * IDirect3DSurface8 implementation
4 * Copyright 2002-2004 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
23 #include "config.h"
25 #include <stdarg.h>
26 #include <stdio.h>
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "wingdi.h"
34 #include "wine/debug.h"
36 #include "d3d8_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
40 /* IDirect3DVolume IUnknown parts follow: */
41 HRESULT WINAPI IDirect3DSurface8Impl_QueryInterface(LPDIRECT3DSURFACE8 iface,REFIID riid,LPVOID *ppobj)
43 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
45 if (IsEqualGUID(riid, &IID_IUnknown)
46 || IsEqualGUID(riid, &IID_IDirect3DSurface8)) {
47 IDirect3DSurface8Impl_AddRef(iface);
48 *ppobj = This;
49 return D3D_OK;
52 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
53 return E_NOINTERFACE;
56 ULONG WINAPI IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) {
57 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
58 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
59 return ++(This->ref);
62 ULONG WINAPI IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) {
63 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
64 ULONG ref = --This->ref;
65 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
66 if (ref == 0) {
67 HeapFree(GetProcessHeap(), 0, This->allocatedMemory);
68 HeapFree(GetProcessHeap(), 0, This);
70 return ref;
73 /* IDirect3DSurface8: */
74 HRESULT WINAPI IDirect3DSurface8Impl_GetDevice(LPDIRECT3DSURFACE8 iface, IDirect3DDevice8** ppDevice) {
75 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
76 TRACE("(%p) : returning %p\n", This, This->Device);
77 *ppDevice = (LPDIRECT3DDEVICE8) This->Device;
78 /**
79 * Note Calling this method will increase the internal reference count
80 * on the IDirect3DDevice8 interface.
82 IDirect3DDevice8Impl_AddRef(*ppDevice);
83 return D3D_OK;
86 HRESULT WINAPI IDirect3DSurface8Impl_SetPrivateData(LPDIRECT3DSURFACE8 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
87 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
88 FIXME("(%p) : stub\n", This);
89 return D3D_OK;
92 HRESULT WINAPI IDirect3DSurface8Impl_GetPrivateData(LPDIRECT3DSURFACE8 iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
93 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
94 FIXME("(%p) : stub\n", This);
95 return D3D_OK;
98 HRESULT WINAPI IDirect3DSurface8Impl_FreePrivateData(LPDIRECT3DSURFACE8 iface, REFGUID refguid) {
99 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
100 FIXME("(%p) : stub\n", This);
101 return D3D_OK;
104 HRESULT WINAPI IDirect3DSurface8Impl_GetContainer(LPDIRECT3DSURFACE8 iface, REFIID riid, void** ppContainer) {
105 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
106 HRESULT res;
107 res = IUnknown_QueryInterface(This->Container, riid, ppContainer);
108 if (E_NOINTERFACE == res) {
110 * If the surface is created using CreateImageSurface, CreateRenderTarget,
111 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
112 * GetContainer will return the Direct3D device used to create the surface.
114 res = IUnknown_QueryInterface(This->Container, &IID_IDirect3DDevice8, ppContainer);
116 TRACE("(%p) : returning %p\n", This, *ppContainer);
117 return res;
120 HRESULT WINAPI IDirect3DSurface8Impl_GetDesc(LPDIRECT3DSURFACE8 iface, D3DSURFACE_DESC *pDesc) {
121 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
123 TRACE("(%p) : copying into %p\n", This, pDesc);
124 memcpy(pDesc, &This->myDesc, sizeof(D3DSURFACE_DESC));
125 return D3D_OK;
128 HRESULT WINAPI IDirect3DSurface8Impl_LockRect(LPDIRECT3DSURFACE8 iface, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
129 HRESULT hr;
130 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
132 /* fixme: should we really lock as such? */
133 if (This->inTexture && This->inPBuffer) {
134 FIXME("Warning: Surface is in texture memory or pbuffer\n");
135 This->inTexture = 0;
136 This->inPBuffer = 0;
139 if (FALSE == This->lockable) {
140 /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
141 texture regions, and since the destination is an unlockable region we need
142 to tolerate this */
143 TRACE("Warning: trying to lock unlockable surf@%p\n", This);
144 /*return D3DERR_INVALIDCALL; */
147 if (This == This->Device->backBuffer || This == This->Device->renderTarget || This == This->Device->frontBuffer || This->Device->depthStencilBuffer) {
148 if (This == This->Device->backBuffer) {
149 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
150 } else if (This == This->Device->frontBuffer) {
151 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
152 } else if (This == This->Device->renderTarget) {
153 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
154 } else if (This == This->Device->depthStencilBuffer) {
155 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
157 } else {
158 TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->allocatedMemory);
161 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
162 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt3/5)
163 ie pitch = (width/4) * bytes per block */
164 if (This->myDesc.Format == D3DFMT_DXT1) /* DXT1 is 8 bytes per block */
165 pLockedRect->Pitch = (This->myDesc.Width/4) * 8;
166 else if (This->myDesc.Format == D3DFMT_DXT3 || This->myDesc.Format == D3DFMT_DXT5) /* DXT3/5 is 16 bytes per block */
167 pLockedRect->Pitch = (This->myDesc.Width/4) * 16;
168 else
169 pLockedRect->Pitch = This->bytesPerPixel * This->myDesc.Width; /* Bytes / row */
171 if (NULL == pRect) {
172 pLockedRect->pBits = This->allocatedMemory;
173 This->lockedRect.left = 0;
174 This->lockedRect.top = 0;
175 This->lockedRect.right = This->myDesc.Width;
176 This->lockedRect.bottom = This->myDesc.Height;
177 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);
178 } else {
179 TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
181 if (This->myDesc.Format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
182 pLockedRect->pBits = This->allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel/2));
183 } else {
184 pLockedRect->pBits = This->allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
186 This->lockedRect.left = pRect->left;
187 This->lockedRect.top = pRect->top;
188 This->lockedRect.right = pRect->right;
189 This->lockedRect.bottom = pRect->bottom;
193 if (0 == This->myDesc.Usage) { /* classic surface */
195 /* Nothing to do ;) */
197 } else if (D3DUSAGE_RENDERTARGET & This->myDesc.Usage && !(Flags&D3DLOCK_DISCARD)) { /* render surfaces */
199 if (This == This->Device->backBuffer || This == This->Device->renderTarget || This == This->Device->frontBuffer) {
200 GLint prev_store;
201 GLenum prev_read;
203 ENTER_GL();
206 * for render->surface copy begin to begin of allocatedMemory
207 * unlock can be more easy
209 pLockedRect->pBits = This->allocatedMemory;
211 glFlush();
212 vcheckGLcall("glFlush");
213 glGetIntegerv(GL_READ_BUFFER, &prev_read);
214 vcheckGLcall("glIntegerv");
215 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
216 vcheckGLcall("glIntegerv");
218 if (This == This->Device->backBuffer) {
219 glReadBuffer(GL_BACK);
220 } else if (This == This->Device->frontBuffer || This == This->Device->renderTarget) {
221 glReadBuffer(GL_FRONT);
222 } else if (This == This->Device->depthStencilBuffer) {
223 ERR("Stencil Buffer lock unsupported for now\n");
225 vcheckGLcall("glReadBuffer");
228 long j;
229 GLenum format = D3DFmt2GLFmt(This->Device, This->myDesc.Format);
230 GLenum type = D3DFmt2GLType(This->Device, This->myDesc.Format);
231 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
232 glReadPixels(This->lockedRect.left,
233 This->lockedRect.bottom - j - 1,
234 This->lockedRect.right - This->lockedRect.left,
236 format,
237 type,
238 (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
239 vcheckGLcall("glReadPixels");
243 glReadBuffer(prev_read);
244 vcheckGLcall("glReadBuffer");
246 LEAVE_GL();
248 } else {
249 FIXME("unsupported locking to Rendering surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
252 } else if (D3DUSAGE_DEPTHSTENCIL & This->myDesc.Usage) { /* stencil surfaces */
254 FIXME("TODO stencil depth surface locking surf@%p usage(%lu)\n", This, This->myDesc.Usage);
256 } else {
257 FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
260 if (Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY)) {
261 /* Don't dirtify */
262 } else {
264 * Dirtify on lock
265 * as seen in msdn docs
267 IDirect3DSurface8Impl_AddDirtyRect(iface, &This->lockedRect);
269 /** Dirtify Container if needed */
270 if (NULL != This->Container) {
271 IDirect3DBaseTexture8* cont = NULL;
272 hr = IUnknown_QueryInterface(This->Container, &IID_IDirect3DBaseTexture8, (void**) &cont);
274 if (SUCCEEDED(hr) && NULL != cont) {
275 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
276 IDirect3DBaseTexture8_Release(cont);
277 cont = NULL;
282 TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Dirty);
284 This->locked = TRUE;
285 return D3D_OK;
288 HRESULT WINAPI IDirect3DSurface8Impl_UnlockRect(LPDIRECT3DSURFACE8 iface) {
289 GLint skipBytes = 0;
290 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
292 if (FALSE == This->locked) {
293 ERR("trying to Unlock an unlocked surf@%p\n", This);
294 return D3DERR_INVALIDCALL;
297 if (This == This->Device->backBuffer || This == This->Device->frontBuffer || This->Device->depthStencilBuffer || This == This->Device->renderTarget) {
298 if (This == This->Device->backBuffer) {
299 TRACE("(%p, backBuffer) : dirtyfied(%d)\n", This, This->Dirty);
300 } else if (This == This->Device->frontBuffer) {
301 TRACE("(%p, frontBuffer) : dirtyfied(%d)\n", This, This->Dirty);
302 } else if (This == This->Device->depthStencilBuffer) {
303 TRACE("(%p, stencilBuffer) : dirtyfied(%d)\n", This, This->Dirty);
304 } else if (This == This->Device->renderTarget) {
305 TRACE("(%p, renderTarget) : dirtyfied(%d)\n", This, This->Dirty);
307 } else {
308 TRACE("(%p) : dirtyfied(%d)\n", This, This->Dirty);
311 if (FALSE == This->Dirty) {
312 TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
313 goto unlock_end;
316 if (0 == This->myDesc.Usage) { /* classic surface */
318 * nothing to do
319 * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
321 } else if (D3DUSAGE_RENDERTARGET & This->myDesc.Usage) { /* render surfaces */
323 if (This == This->Device->backBuffer || This == This->Device->frontBuffer || This == This->Device->renderTarget) {
324 GLint prev_store;
325 GLenum prev_draw;
326 GLint prev_rasterpos[4];
328 ENTER_GL();
330 glFlush();
331 vcheckGLcall("glFlush");
332 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
333 vcheckGLcall("glIntegerv");
334 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
335 vcheckGLcall("glIntegerv");
336 glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
337 vcheckGLcall("glIntegerv");
338 glPixelZoom(1.0, -1.0);
339 vcheckGLcall("glPixelZoom");
341 /* glDrawPixels transforms the raster position as though it was a vertex -
342 we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
343 per drawprim (and leave set - it will sort itself out due to last_was_rhw */
344 if (!This->Device->last_was_rhw) {
346 double X, Y, height, width, minZ, maxZ;
347 This->Device->last_was_rhw = TRUE;
349 /* Transformed already into viewport coordinates, so we do not need transform
350 matrices. Reset all matrices to identity and leave the default matrix in world
351 mode. */
352 glMatrixMode(GL_MODELVIEW);
353 checkGLcall("glMatrixMode");
354 glLoadIdentity();
355 checkGLcall("glLoadIdentity");
357 glMatrixMode(GL_PROJECTION);
358 checkGLcall("glMatrixMode");
359 glLoadIdentity();
360 checkGLcall("glLoadIdentity");
362 /* Set up the viewport to be full viewport */
363 X = This->Device->StateBlock->viewport.X;
364 Y = This->Device->StateBlock->viewport.Y;
365 height = This->Device->StateBlock->viewport.Height;
366 width = This->Device->StateBlock->viewport.Width;
367 minZ = This->Device->StateBlock->viewport.MinZ;
368 maxZ = This->Device->StateBlock->viewport.MaxZ;
369 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
370 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
371 checkGLcall("glOrtho");
373 /* Window Coord 0 is the middle of the first pixel, so translate by half
374 a pixel (See comment above glTranslate below) */
375 glTranslatef(0.5, 0.5, 0);
376 checkGLcall("glTranslatef(0.5, 0.5, 0)");
379 if (This == This->Device->backBuffer) {
380 glDrawBuffer(GL_BACK);
381 } else if (This == This->Device->frontBuffer || This == This->Device->renderTarget) {
382 glDrawBuffer(GL_FRONT);
384 vcheckGLcall("glDrawBuffer");
386 /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
387 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
388 glPixelStorei(GL_UNPACK_ROW_LENGTH, This->myDesc.Width);
390 /* And back buffers are not blended */
391 glDisable(GL_BLEND);
393 glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
394 vcheckGLcall("glRasterPos2f");
395 switch (This->myDesc.Format) {
396 case D3DFMT_R5G6B5:
398 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
399 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->allocatedMemory);
400 vcheckGLcall("glDrawPixels");
402 break;
403 case D3DFMT_R8G8B8:
405 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
406 GL_RGB, GL_UNSIGNED_BYTE, This->allocatedMemory);
407 vcheckGLcall("glDrawPixels");
409 break;
410 case D3DFMT_A8R8G8B8:
412 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
413 vcheckGLcall("glPixelStorei");
414 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
415 GL_BGRA, GL_UNSIGNED_BYTE, This->allocatedMemory);
416 vcheckGLcall("glDrawPixels");
417 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
418 vcheckGLcall("glPixelStorei");
420 break;
421 default:
422 FIXME("Unsupported Format %u in locking func\n", This->myDesc.Format);
425 glPixelZoom(1.0,1.0);
426 vcheckGLcall("glPixelZoom");
427 glDrawBuffer(prev_draw);
428 vcheckGLcall("glDrawBuffer");
429 glRasterPos3iv(&prev_rasterpos[0]);
430 vcheckGLcall("glRasterPos3iv");
432 /* Reset to previous pack row length / blending state */
433 glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
434 if (This->Device->StateBlock->renderstate[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
436 LEAVE_GL();
438 /** restore clean dirty state */
439 IDirect3DSurface8Impl_CleanDirtyRect(iface);
441 } else {
442 FIXME("unsupported unlocking to Rendering surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
445 } else if (D3DUSAGE_DEPTHSTENCIL & This->myDesc.Usage) { /* stencil surfaces */
447 if (This == This->Device->depthStencilBuffer) {
448 FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->myDesc.Usage);
449 } else {
450 FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
453 } else {
454 FIXME("unsupported unlocking to surface surf@%p usage(%lu)\n", This, This->myDesc.Usage);
457 unlock_end:
458 This->locked = FALSE;
459 memset(&This->lockedRect, 0, sizeof(RECT));
460 return D3D_OK;
464 IDirect3DSurface8Vtbl Direct3DSurface8_Vtbl =
466 IDirect3DSurface8Impl_QueryInterface,
467 IDirect3DSurface8Impl_AddRef,
468 IDirect3DSurface8Impl_Release,
469 IDirect3DSurface8Impl_GetDevice,
470 IDirect3DSurface8Impl_SetPrivateData,
471 IDirect3DSurface8Impl_GetPrivateData,
472 IDirect3DSurface8Impl_FreePrivateData,
473 IDirect3DSurface8Impl_GetContainer,
474 IDirect3DSurface8Impl_GetDesc,
475 IDirect3DSurface8Impl_LockRect,
476 IDirect3DSurface8Impl_UnlockRect,
480 HRESULT WINAPI IDirect3DSurface8Impl_LoadTexture(LPDIRECT3DSURFACE8 iface, GLenum gl_target, GLenum gl_level) {
481 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
483 if (This->inTexture)
484 return D3D_OK;
485 if (This->inPBuffer) {
486 ENTER_GL();
487 if (gl_level != 0)
488 FIXME("Surface in texture is only supported for level 0\n");
489 else if (This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8 ||
490 This->myDesc.Format == D3DFMT_DXT1 || This->myDesc.Format == D3DFMT_DXT3 ||
491 This->myDesc.Format == D3DFMT_DXT5)
492 FIXME("Format %d not supported\n", This->myDesc.Format);
493 else {
494 glCopyTexImage2D(gl_target,
496 D3DFmt2GLIntFmt(This->Device,
497 This->myDesc.Format),
499 0,/*This->surfaces[j][i]->myDesc.Height-1,*/
500 This->myDesc.Width,
501 This->myDesc.Height,
503 TRACE("Updating target %d\n", gl_target);
504 This->inTexture = TRUE;
506 LEAVE_GL();
507 return D3D_OK;
510 if ((This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8) &&
511 !GL_SUPPORT_DEV(EXT_PALETTED_TEXTURE, This->Device)) {
513 * wanted a paletted texture and not really support it in HW
514 * so software emulation code begin
516 UINT i;
517 PALETTEENTRY* pal = This->Device->palettes[This->Device->currentPalette];
518 VOID* surface = (VOID*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->myDesc.Width * This->myDesc.Height * sizeof(DWORD));
519 BYTE* dst = (BYTE*) surface;
520 BYTE* src = (BYTE*) This->allocatedMemory;
522 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
523 BYTE color = *src++;
524 *dst++ = pal[color].peRed;
525 *dst++ = pal[color].peGreen;
526 *dst++ = pal[color].peBlue;
527 if (This->myDesc.Format == D3DFMT_A8P8)
528 *dst++ = pal[color].peFlags;
529 else
530 *dst++ = 0xFF;
533 ENTER_GL();
535 TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
536 gl_target,
537 gl_level,
538 GL_RGBA,
539 This->myDesc.Width,
540 This->myDesc.Height,
542 GL_RGBA,
543 GL_UNSIGNED_BYTE,
544 surface);
545 glTexImage2D(gl_target,
546 gl_level,
547 GL_RGBA,
548 This->myDesc.Width,
549 This->myDesc.Height,
551 GL_RGBA,
552 GL_UNSIGNED_BYTE,
553 surface);
554 checkGLcall("glTexImage2D");
555 HeapFree(GetProcessHeap(), 0, surface);
557 LEAVE_GL();
559 return D3D_OK;
562 if (This->myDesc.Format == D3DFMT_DXT1 ||
563 This->myDesc.Format == D3DFMT_DXT3 ||
564 This->myDesc.Format == D3DFMT_DXT5) {
565 if (GL_SUPPORT_DEV(EXT_TEXTURE_COMPRESSION_S3TC, This->Device)) {
566 TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
567 gl_target,
568 gl_level,
569 D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
570 This->myDesc.Width,
571 This->myDesc.Height,
573 This->myDesc.Size,
574 This->allocatedMemory);
576 ENTER_GL();
578 GL_EXTCALL_DEV(glCompressedTexImage2DARB, This->Device)(gl_target,
579 gl_level,
580 D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
581 This->myDesc.Width,
582 This->myDesc.Height,
584 This->myDesc.Size,
585 This->allocatedMemory);
586 checkGLcall("glCommpressedTexTexImage2D");
588 LEAVE_GL();
589 } else {
590 FIXME("Using DXT1/3/5 without advertized support\n");
592 } else {
594 TRACE("Calling glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
595 gl_target,
596 gl_level,
597 debug_d3dformat(This->myDesc.Format),
598 D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
599 This->myDesc.Width,
600 This->myDesc.Height,
602 D3DFmt2GLFmt(This->Device, This->myDesc.Format),
603 D3DFmt2GLType(This->Device, This->myDesc.Format),
604 This->allocatedMemory);
606 ENTER_GL();
608 glTexImage2D(gl_target,
609 gl_level,
610 D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
611 This->myDesc.Width,
612 This->myDesc.Height,
614 D3DFmt2GLFmt(This->Device, This->myDesc.Format),
615 D3DFmt2GLType(This->Device, This->myDesc.Format),
616 This->allocatedMemory);
617 checkGLcall("glTexImage2D");
619 LEAVE_GL();
621 #if 0
623 static unsigned int gen = 0;
624 char buffer[4096];
625 ++gen;
626 if ((gen % 10) == 0) {
627 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, gl_target, gl_level, gen);
628 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This, buffer);
631 * debugging crash code
632 if (gen == 250) {
633 void** test = NULL;
634 *test = 0;
638 #endif
641 return D3D_OK;
644 #include <errno.h>
645 HRESULT WINAPI IDirect3DSurface8Impl_SaveSnapshot(LPDIRECT3DSURFACE8 iface, const char* filename) {
646 FILE* f = NULL;
647 ULONG i;
648 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
650 f = fopen(filename, "w+");
651 if (NULL == f) {
652 ERR("opening of %s failed with: %s\n", filename, strerror(errno));
653 return D3DERR_INVALIDCALL;
656 TRACE("opened %s with format %s\n", filename, debug_d3dformat(This->myDesc.Format));
658 fprintf(f, "P6\n%u %u\n255\n", This->myDesc.Width, This->myDesc.Height);
659 switch (This->myDesc.Format) {
660 case D3DFMT_X8R8G8B8:
661 case D3DFMT_A8R8G8B8:
663 DWORD color;
664 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
665 color = ((DWORD*) This->allocatedMemory)[i];
666 fputc((color >> 16) & 0xFF, f);
667 fputc((color >> 8) & 0xFF, f);
668 fputc((color >> 0) & 0xFF, f);
671 break;
672 case D3DFMT_R8G8B8:
674 BYTE* color;
675 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
676 color = ((BYTE*) This->allocatedMemory) + (3 * i);
677 fputc((color[0]) & 0xFF, f);
678 fputc((color[1]) & 0xFF, f);
679 fputc((color[2]) & 0xFF, f);
682 break;
683 case D3DFMT_A1R5G5B5:
685 WORD color;
686 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
687 color = ((WORD*) This->allocatedMemory)[i];
688 fputc(((color >> 10) & 0x1F) * 255 / 31, f);
689 fputc(((color >> 5) & 0x1F) * 255 / 31, f);
690 fputc(((color >> 0) & 0x1F) * 255 / 31, f);
693 break;
694 case D3DFMT_A4R4G4B4:
696 WORD color;
697 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
698 color = ((WORD*) This->allocatedMemory)[i];
699 fputc(((color >> 8) & 0x0F) * 255 / 15, f);
700 fputc(((color >> 4) & 0x0F) * 255 / 15, f);
701 fputc(((color >> 0) & 0x0F) * 255 / 15, f);
704 break;
706 case D3DFMT_R5G6B5:
708 WORD color;
709 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
710 color = ((WORD*) This->allocatedMemory)[i];
711 fputc(((color >> 11) & 0x1F) * 255 / 31, f);
712 fputc(((color >> 5) & 0x3F) * 255 / 63, f);
713 fputc(((color >> 0) & 0x1F) * 255 / 31, f);
716 break;
717 default:
718 FIXME("Unimplemented dump mode format(%u,%s)\n", This->myDesc.Format, debug_d3dformat(This->myDesc.Format));
720 fclose(f);
721 return D3D_OK;
724 HRESULT WINAPI IDirect3DSurface8Impl_CleanDirtyRect(LPDIRECT3DSURFACE8 iface) {
725 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
726 This->Dirty = FALSE;
727 This->dirtyRect.left = This->myDesc.Width;
728 This->dirtyRect.top = This->myDesc.Height;
729 This->dirtyRect.right = 0;
730 This->dirtyRect.bottom = 0;
731 return D3D_OK;
735 * Raphael:
736 * very stupid way to handle multiple dirty rects but it works :)
738 extern HRESULT WINAPI IDirect3DSurface8Impl_AddDirtyRect(LPDIRECT3DSURFACE8 iface, CONST RECT* pDirtyRect) {
739 IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
740 This->Dirty = TRUE;
741 if (NULL != pDirtyRect) {
742 This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left);
743 This->dirtyRect.top = min(This->dirtyRect.top, pDirtyRect->top);
744 This->dirtyRect.right = max(This->dirtyRect.right, pDirtyRect->right);
745 This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
746 } else {
747 This->dirtyRect.left = 0;
748 This->dirtyRect.top = 0;
749 This->dirtyRect.right = This->myDesc.Width;
750 This->dirtyRect.bottom = This->myDesc.Height;
752 return D3D_OK;