Authors: Christian Costa <titan.costa@wanadoo.fr>, Jason Edmeades <us@the-edmeades...
[wine/multimedia.git] / dlls / d3d8 / surface.c
blobc4fb500ccfc143cc6a719104e0278efbf263b505
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 ICOM_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 ICOM_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 ICOM_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 ICOM_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 ICOM_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 ICOM_THIS(IDirect3DSurface8Impl,iface);
94 FIXME("(%p) : stub\n", This);
95 return D3D_OK;
98 HRESULT WINAPI IDirect3DSurface8Impl_FreePrivateData(LPDIRECT3DSURFACE8 iface, REFGUID refguid) {
99 ICOM_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 ICOM_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 ICOM_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 ICOM_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**)(char*) &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 ICOM_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 ICOM_VTABLE(IDirect3DSurface8) Direct3DSurface8_Vtbl =
466 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
467 IDirect3DSurface8Impl_QueryInterface,
468 IDirect3DSurface8Impl_AddRef,
469 IDirect3DSurface8Impl_Release,
470 IDirect3DSurface8Impl_GetDevice,
471 IDirect3DSurface8Impl_SetPrivateData,
472 IDirect3DSurface8Impl_GetPrivateData,
473 IDirect3DSurface8Impl_FreePrivateData,
474 IDirect3DSurface8Impl_GetContainer,
475 IDirect3DSurface8Impl_GetDesc,
476 IDirect3DSurface8Impl_LockRect,
477 IDirect3DSurface8Impl_UnlockRect,
481 HRESULT WINAPI IDirect3DSurface8Impl_LoadTexture(LPDIRECT3DSURFACE8 iface, GLenum gl_target, GLenum gl_level) {
482 ICOM_THIS(IDirect3DSurface8Impl,iface);
484 if (This->inTexture)
485 return D3D_OK;
486 if (This->inPBuffer) {
487 ENTER_GL();
488 if (gl_level != 0)
489 FIXME("Surface in texture is only supported for level 0\n");
490 else if (This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8 ||
491 This->myDesc.Format == D3DFMT_DXT1 || This->myDesc.Format == D3DFMT_DXT3 ||
492 This->myDesc.Format == D3DFMT_DXT5)
493 FIXME("Format %d not supported\n", This->myDesc.Format);
494 else {
495 glCopyTexImage2D(gl_target,
497 D3DFmt2GLIntFmt(This->Device,
498 This->myDesc.Format),
500 0,/*This->surfaces[j][i]->myDesc.Height-1,*/
501 This->myDesc.Width,
502 This->myDesc.Height,
504 TRACE("Updating target %d\n", gl_target);
505 This->inTexture = TRUE;
507 LEAVE_GL();
508 return D3D_OK;
511 if ((This->myDesc.Format == D3DFMT_P8 || This->myDesc.Format == D3DFMT_A8P8) &&
512 !GL_SUPPORT_DEV(EXT_PALETTED_TEXTURE, This->Device)) {
514 * wanted a paletted texture and not really support it in HW
515 * so software emulation code begin
517 UINT i;
518 PALETTEENTRY* pal = This->Device->palettes[This->Device->currentPalette];
519 VOID* surface = (VOID*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->myDesc.Width * This->myDesc.Height * sizeof(DWORD));
520 BYTE* dst = (BYTE*) surface;
521 BYTE* src = (BYTE*) This->allocatedMemory;
523 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
524 BYTE color = *src++;
525 *dst++ = pal[color].peRed;
526 *dst++ = pal[color].peGreen;
527 *dst++ = pal[color].peBlue;
528 if (This->myDesc.Format == D3DFMT_A8P8)
529 *dst++ = pal[color].peFlags;
530 else
531 *dst++ = 0xFF;
534 ENTER_GL();
536 TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
537 gl_target,
538 gl_level,
539 GL_RGBA,
540 This->myDesc.Width,
541 This->myDesc.Height,
543 GL_RGBA,
544 GL_UNSIGNED_BYTE,
545 surface);
546 glTexImage2D(gl_target,
547 gl_level,
548 GL_RGBA,
549 This->myDesc.Width,
550 This->myDesc.Height,
552 GL_RGBA,
553 GL_UNSIGNED_BYTE,
554 surface);
555 checkGLcall("glTexImage2D");
556 HeapFree(GetProcessHeap(), 0, surface);
558 LEAVE_GL();
560 return D3D_OK;
563 if (This->myDesc.Format == D3DFMT_DXT1 ||
564 This->myDesc.Format == D3DFMT_DXT3 ||
565 This->myDesc.Format == D3DFMT_DXT5) {
566 if (GL_SUPPORT_DEV(EXT_TEXTURE_COMPRESSION_S3TC, This->Device)) {
567 TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
568 gl_target,
569 gl_level,
570 D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
571 This->myDesc.Width,
572 This->myDesc.Height,
574 This->myDesc.Size,
575 This->allocatedMemory);
577 ENTER_GL();
579 GL_EXTCALL_DEV(glCompressedTexImage2DARB, This->Device)(gl_target,
580 gl_level,
581 D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
582 This->myDesc.Width,
583 This->myDesc.Height,
585 This->myDesc.Size,
586 This->allocatedMemory);
587 checkGLcall("glCommpressedTexTexImage2D");
589 LEAVE_GL();
590 } else {
591 FIXME("Using DXT1/3/5 without advertized support\n");
593 } else {
594 TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
595 gl_target,
596 gl_level,
597 D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
598 This->myDesc.Width,
599 This->myDesc.Height,
601 D3DFmt2GLFmt(This->Device, This->myDesc.Format),
602 D3DFmt2GLType(This->Device, This->myDesc.Format),
603 This->allocatedMemory);
605 ENTER_GL();
607 glTexImage2D(gl_target,
608 gl_level,
609 D3DFmt2GLIntFmt(This->Device, This->myDesc.Format),
610 This->myDesc.Width,
611 This->myDesc.Height,
613 D3DFmt2GLFmt(This->Device, This->myDesc.Format),
614 D3DFmt2GLType(This->Device, This->myDesc.Format),
615 This->allocatedMemory);
616 checkGLcall("glTexImage2D");
618 LEAVE_GL();
620 #if 0
622 static unsigned int gen = 0;
623 char buffer[4096];
624 ++gen;
625 if ((gen % 10) == 0) {
626 snprintf(buffer, sizeof(buffer), "/tmp/surface%u_level%u_%u.ppm", gl_target, gl_level, gen);
627 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This, buffer);
630 #endif
633 return D3D_OK;
636 #include <errno.h>
637 HRESULT WINAPI IDirect3DSurface8Impl_SaveSnapshot(LPDIRECT3DSURFACE8 iface, const char* filename) {
638 FILE* f = NULL;
639 ULONG i;
640 ICOM_THIS(IDirect3DSurface8Impl,iface);
642 f = fopen(filename, "w+");
643 if (NULL == f) {
644 ERR("opening of %s failed with: %s\n", filename, strerror(errno));
645 return D3DERR_INVALIDCALL;
648 TRACE("opened %s with format %s\n", filename, debug_d3dformat(This->myDesc.Format));
650 fprintf(f, "P6\n%u %u\n255\n", This->myDesc.Width, This->myDesc.Height);
651 switch (This->myDesc.Format) {
652 case D3DFMT_X8R8G8B8:
653 case D3DFMT_A8R8G8B8:
655 DWORD color;
656 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
657 color = ((DWORD*) This->allocatedMemory)[i];
658 fputc((color >> 16) & 0xFF, f);
659 fputc((color >> 8) & 0xFF, f);
660 fputc((color >> 0) & 0xFF, f);
663 break;
664 case D3DFMT_R8G8B8:
666 BYTE* color;
667 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
668 color = ((BYTE*) This->allocatedMemory) + (3 * i);
669 fputc((color[0]) & 0xFF, f);
670 fputc((color[1]) & 0xFF, f);
671 fputc((color[2]) & 0xFF, f);
674 break;
675 case D3DFMT_A1R5G5B5:
677 WORD color;
678 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
679 color = ((WORD*) This->allocatedMemory)[i];
680 fputc(((color >> 10) & 0x1F) * 255 / 31, f);
681 fputc(((color >> 5) & 0x1F) * 255 / 31, f);
682 fputc(((color >> 0) & 0x1F) * 255 / 31, f);
685 break;
686 case D3DFMT_A4R4G4B4:
688 WORD color;
689 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
690 color = ((WORD*) This->allocatedMemory)[i];
691 fputc(((color >> 8) & 0x0F) * 255 / 15, f);
692 fputc(((color >> 4) & 0x0F) * 255 / 15, f);
693 fputc(((color >> 0) & 0x0F) * 255 / 15, f);
696 break;
698 case D3DFMT_R5G6B5:
700 WORD color;
701 for (i = 0; i < This->myDesc.Width * This->myDesc.Height; i++) {
702 color = ((WORD*) This->allocatedMemory)[i];
703 fputc(((color >> 11) & 0x1F) * 255 / 31, f);
704 fputc(((color >> 5) & 0x3F) * 255 / 63, f);
705 fputc(((color >> 0) & 0x1F) * 255 / 31, f);
708 break;
709 default:
710 FIXME("Unimplemented dump mode format(%u,%s)\n", This->myDesc.Format, debug_d3dformat(This->myDesc.Format));
712 fclose(f);
713 return D3D_OK;
716 HRESULT WINAPI IDirect3DSurface8Impl_CleanDirtyRect(LPDIRECT3DSURFACE8 iface) {
717 ICOM_THIS(IDirect3DSurface8Impl,iface);
718 This->Dirty = FALSE;
719 This->dirtyRect.left = This->myDesc.Width;
720 This->dirtyRect.top = This->myDesc.Height;
721 This->dirtyRect.right = 0;
722 This->dirtyRect.bottom = 0;
723 return D3D_OK;
727 * Raphael:
728 * very stupid way to handle multiple dirty rects but it works :)
730 extern HRESULT WINAPI IDirect3DSurface8Impl_AddDirtyRect(LPDIRECT3DSURFACE8 iface, CONST RECT* pDirtyRect) {
731 ICOM_THIS(IDirect3DSurface8Impl,iface);
732 This->Dirty = TRUE;
733 if (NULL != pDirtyRect) {
734 This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left);
735 This->dirtyRect.top = min(This->dirtyRect.top, pDirtyRect->top);
736 This->dirtyRect.right = max(This->dirtyRect.right, pDirtyRect->right);
737 This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
738 } else {
739 This->dirtyRect.left = 0;
740 This->dirtyRect.top = 0;
741 This->dirtyRect.right = This->myDesc.Width;
742 This->dirtyRect.bottom = This->myDesc.Height;
744 return D3D_OK;