source: trunk/src/ddraw/surfblit.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 52.1 KB
Line 
1/* $Id: surfblit.cpp,v 1.3 2003-01-21 11:20:36 sandervl Exp $ */
2
3/*
4 * DirectDraw Surface class implementaion
5 *
6 * Copyright 1999 Markus Montkowski
7 * Copyright 2000 Michal Necasek
8 * Copyright 1998-2001 Sander van Leeuwen
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13
14#define _OS2WIN_H
15#define FAR
16
17#include <odin.h>
18#include <winbase.h>
19#include <stdlib.h>
20#include <string.h>
21#include <memory.h>
22#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
23 ( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) | \
24 ( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
25#include <fourcc.h>
26
27#define CINTERFACE
28#include "ddraw2d.h"
29#include "clipper.h"
30#include "palette.h"
31#include "surface.h"
32#include "surfacehlp.h"
33#include "os2util.h"
34#include "rectangle.h"
35
36#include <misc.h>
37#include "asmutil.h"
38#include "bltFunc.h"
39#include "colorconv.h"
40#include "fillfunc.h"
41#include <winerror.h>
42#include <os2win.h>
43#include <cpuhlp.h>
44#include "asmutil.h"
45#include "wndproc.h"
46#include "divewrap.h"
47
48#ifdef __IBMC__
49 #include <builtin.h>
50#endif
51
52
53
54//******************************************************************************
55//******************************************************************************
56HRESULT WIN32API SurfBlt(THIS This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE2 lpDDSrcSurface,
57 LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
58{
59 return SurfBlt4( This,
60 lpDestRect,
61 (LPDIRECTDRAWSURFACE4)lpDDSrcSurface,
62 lpSrcRect,
63 dwFlags,
64 lpDDBltFx);
65}
66//******************************************************************************
67//******************************************************************************
68HRESULT WIN32API SurfBlt3(THIS This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE3 lpDDSrcSurface,
69 LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
70{
71 return SurfBlt4( This,
72 lpDestRect,
73 (LPDIRECTDRAWSURFACE4)lpDDSrcSurface,
74 lpSrcRect,
75 dwFlags,
76 lpDDBltFx);
77}
78//******************************************************************************
79//******************************************************************************
80HRESULT WIN32API SurfBlt4(THIS This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE4 lpDDSrcSurface,
81 LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
82{
83 OS2IDirectDrawSurface *dest = (OS2IDirectDrawSurface *)This;
84 OS2IDirectDrawSurface *src = (OS2IDirectDrawSurface *)lpDDSrcSurface;
85
86 DDSURFACEDESC2 DestSurfaceDesc, SrcSurfaceDesc;
87 DDRectangle *pIRectDest,*pIRectSrc,*pIRectTest;
88 RECT DestRect, SrcRect;
89 BOOL Found;
90 int i;
91 HRESULT ret = DD_OK;
92
93 dprintf(("DDRAW: SurfBlt4 To Surf %08X, from Surf %08X\n",dest,src));
94 if ( (NULL!=lpDestRect)&& (NULL!=lpSrcRect))
95 dprintf(("DDRAW: SurfBlt4 to (%d,%d)(%d,%d) at %08X from (%d,%d)(%d,%d) at %08X\n", lpDestRect->left, lpDestRect->top,
96 lpDestRect->right, lpDestRect->bottom, dest, lpSrcRect->left, lpSrcRect->top,
97 lpSrcRect->right, lpSrcRect->bottom, src));
98
99 _dump_DDBLT(dwFlags);
100
101 if (NULL!=lpDestRect)
102 {
103 // HACK: RA does pass in negative values we might be better return an error,
104 //for now we clip
105#define RA_HACK 1
106
107#ifdef RA_HACK
108 int top,left,bottom,right;
109
110 top = lpDestRect->top;
111 left = lpDestRect->left;
112 bottom = lpDestRect->bottom;
113 right = lpDestRect->right;
114
115 if(top<0)
116 {
117 bottom += top;
118 top = 0;
119 }
120
121 if(top > dest->height)
122 return DDERR_INVALIDPARAMS;
123
124 if(bottom<0)
125 return DDERR_INVALIDPARAMS;
126
127 if(bottom>dest->height)
128 bottom=dest->height;
129
130 if(left<0)
131 {
132 right += left;
133 left = 0;
134 }
135
136 if(left>dest->width)
137 return DDERR_INVALIDPARAMS;
138
139 if(right<0)
140 return DDERR_INVALIDPARAMS;
141
142 if(right>dest->width)
143 right = dest->width;
144#endif // RA_HACK
145
146 pIRectDest = new DDRectangle( left, top, right, bottom);
147#ifdef RA_HACK
148 DestRect.top = top;
149 DestRect.left = left;
150 DestRect.bottom = bottom;
151 DestRect.right = right;
152#else
153 memcpy(&DestRect,lpDestRect,sizeof(RECT) );
154#endif //RA_HACK
155 }
156 else
157 {
158 pIRectDest = new DDRectangle( 0, 0, dest->width, dest->height);
159 DestRect.top = 0;
160 DestRect.left = 0;
161 DestRect.bottom = dest->height;
162 DestRect.right = dest->width;
163 }
164
165 if(dest->fLocked)
166 {
167 if (NULL==lpDestRect)
168 {
169 // If anything is locked we can't blit to the complete surface as
170 // a part is locked
171 Found = TRUE;
172 }
173 else
174 {
175 // If the dest Rectangle intersects with any of the locked rectangles
176 // we can't blit to it
177
178 Found = FALSE;
179 i=0;
180 while( (i<DPA_GetPtrCount(dest->DPA_LockedRects)) && !Found)
181 {
182 pIRectTest = (DDRectangle*) DPA_FastGetPtr(dest->DPA_LockedRects,i);
183 Found = pIRectDest->intersects(*pIRectTest);
184 i++;
185 }
186
187 }
188 if (Found)
189 {
190 delete pIRectDest;
191 dprintf(("DDRAW: Blt: Dest Surface partially locked\n"));
192 return(DDERR_SURFACEBUSY);
193 }
194 }
195 delete pIRectDest;
196
197 //src == NULL for colorfill
198 if(src)
199 {
200 if (NULL!=lpSrcRect)
201 {
202#ifdef RA_HACK
203 // Same as for dest rectangle now for src
204
205 int top,left,bottom,right;
206
207 top = lpSrcRect->top;
208 left = lpSrcRect->left;
209 bottom = lpSrcRect->bottom;
210 right = lpSrcRect->right;
211
212 if(top<0)
213 {
214 bottom += top;
215 top = 0;
216 }
217
218 if(top > src->height)
219 return DDERR_INVALIDPARAMS;
220
221 if(bottom<0)
222 return DDERR_INVALIDPARAMS;
223
224 if(bottom>src->height)
225 bottom=src->height;
226
227 if(left<0)
228 {
229 right += left;
230 left = 0;
231 }
232
233 if(left>src->width)
234 return DDERR_INVALIDPARAMS;
235
236 if(right<0)
237 return DDERR_INVALIDPARAMS;
238
239 if(right>src->width)
240 right = src->width;
241#endif // RA_HACK
242
243 pIRectSrc = new DDRectangle( left, top, right, bottom );
244#ifdef RA_HACK
245 SrcRect.top = top;
246 SrcRect.left = left;
247 SrcRect.bottom = bottom;
248 SrcRect.right = right;
249#else
250 memcpy(&SrcRect,lpSrcRect,sizeof(RECT) );
251#endif
252 }
253 else
254 {
255 pIRectSrc = new DDRectangle( 0, 0, src->width, src->height);
256 SrcRect.top = 0;
257 SrcRect.left = 0;
258 SrcRect.bottom = src->height;
259 SrcRect.right = src->width;
260 }
261
262 if(src->fLocked)
263 {
264 if (NULL==lpSrcRect)
265 {
266 // If anything is locked we can't blit from the complete surface as
267 // a part is locked
268 Found = TRUE;
269 }
270 else
271 {
272 // If the src Rectangle intersects with any of the locked rectangles of the
273 // source surface we can't blit from it
274
275 Found = FALSE;
276 i=0;
277
278 while((i<DPA_GetPtrCount(src->DPA_LockedRects) ) && !Found)
279 {
280 pIRectTest = (DDRectangle*) DPA_FastGetPtr(src->DPA_LockedRects,i);
281 Found = pIRectDest->intersects(*pIRectTest);
282 i++;
283 }
284
285 }
286
287 if (Found)
288 {
289 delete pIRectSrc;
290 dprintf(("DDRAW: Blt: Src Surface partly locked\n"));
291
292 return(DDERR_SURFACEBUSY);
293 }
294 }
295 delete pIRectSrc;
296 } //if(src)
297
298#if 0
299 if(dest->diveBufNr == DIVE_BUFFER_SCREEN &&
300 !(dwFlags & (DDBLT_COLORFILL|DDBLT_DEPTHFILL|DDBLT_ROP) ) &&
301 dest->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount > 8 &&
302 src->DDSurfaceDesc.ddpfPixelFormat.dwRGBBitCount > 8)
303 {
304 int rc, temp, fChanged = FALSE;
305 int destheight = RECT_HEIGHT(&DestRect);
306 int destwidth = RECT_WIDTH(&DestRect);
307 int srcheight = RECT_HEIGHT(&SrcRect);
308 int srcwidth = RECT_WIDTH(&SrcRect);
309
310 //if full surface blit or stretching blit, then use Dive
311 if( (src->DDSurfaceDesc.dwHeight == srcheight &&
312 src->DDSurfaceDesc.dwWidth == srcwidth) ||
313 (srcwidth != destwidth && srcheight != destheight) )
314 {
315 SETUP_BLITTER sBlt = {0};
316
317 sBlt.ulStructLen = sizeof(sBlt);
318 sBlt.fInvert = 0;
319 sBlt.fccSrcColorFormat = src->DDSurfaceDesc.ddpfPixelFormat.dwFourCC;
320 sBlt.ulSrcWidth = srcwidth;
321 sBlt.ulSrcHeight = srcheight;
322 sBlt.ulSrcPosX = SrcRect.left;
323 sBlt.ulSrcPosY = src->DDSurfaceDesc.dwHeight-SrcRect.bottom;
324 sBlt.ulDitherType = 0;
325 sBlt.fccDstColorFormat = dest->DDSurfaceDesc.ddpfPixelFormat.dwFourCC;
326 sBlt.ulDstWidth = destwidth;
327 sBlt.ulDstHeight = destheight;
328 sBlt.lDstPosX = 0;
329 sBlt.lDstPosY = 0;
330 sBlt.lScreenPosX = DestRect.left;
331 sBlt.lScreenPosY = dest->DDSurfaceDesc.dwHeight-DestRect.bottom;
332 sBlt.ulNumDstRects = DIVE_FULLY_VISIBLE;
333 sBlt.pVisDstRects = NULL;
334
335 if(dest->lpClipper && dest->lpClipper->IsClipListChangedInt())
336 {
337 DWORD rgnsize;
338 if(ClipGetClipList((IDirectDrawClipper*)dest->lpClipper, NULL, NULL, &rgnsize) == DD_OK)
339 {
340 LPRGNDATA lpRgnData = (LPRGNDATA)alloca(rgnsize);
341 if(lpRgnData == NULL) {
342 DebugInt3();
343 goto dodiveblit;
344 }
345 if(ClipGetClipList((IDirectDrawClipper*)dest->lpClipper, NULL, lpRgnData, &rgnsize) == DD_OK)
346 {
347 OS2RECTL *pRectl = (OS2RECTL *)&lpRgnData->Buffer;
348
349 if(sBlt.ulNumDstRects == 0) {
350 dprintf(("empty cliplist, return"));
351 return DD_OK;
352 }
353 dprintf(("visible region"));
354 for(i=0;i<lpRgnData->rdh.nCount;i++)
355 {
356 //win32 -> os2 coordinates (region data in screen coordinates)
357 temp = pRectl[i].yTop;
358 pRectl[i].yTop = src->lpDraw->GetScreenHeight() - pRectl[i].yBottom;
359 pRectl[i].yBottom = src->lpDraw->GetScreenHeight() - temp;
360 dprintf(("(%d,%d)(%d,%d)", pRectl[i].xLeft, pRectl[i].yBottom, pRectl[i].xRight, pRectl[i].yTop));
361
362 //clip rectangle must be relative to lScreenPos
363 pRectl[i].xLeft -= sBlt.lScreenPosX;
364 pRectl[i].xRight -= sBlt.lScreenPosX;
365 pRectl[i].yTop -= sBlt.lScreenPosY;
366 pRectl[i].yBottom -= sBlt.lScreenPosY;
367 dprintf(("(%d,%d)(%d,%d)", pRectl[i].xLeft, pRectl[i].yBottom, pRectl[i].xRight, pRectl[i].yTop));
368 }
369 fChanged = TRUE;
370 sBlt.ulNumDstRects = lpRgnData->rdh.nCount;
371 sBlt.pVisDstRects = (PRECTL)&lpRgnData->Buffer;
372 }
373 }
374 }
375dodiveblit:
376#ifdef PERFTEST
377 QueryPerformanceCounter(&liStart);
378#endif
379 if(fChanged || memcmp(&sBlt, &dest->sBlt, sizeof(sBlt)-sizeof(PRECTL)-sizeof(ULONG)))
380 {
381 dprintf(("Setting up blitter: src (%d,%d)(%d,%d)", sBlt.ulSrcPosX, sBlt.ulSrcPosY, sBlt.ulSrcWidth, sBlt.ulSrcHeight));
382 dprintf(("Setting up blitter: dest (%d,%d)(%d,%d)", sBlt.lScreenPosX, sBlt.lScreenPosY, sBlt.ulDstWidth, sBlt.ulDstHeight));
383 rc = DiveSetupBlitter(dest->hDive, &sBlt);
384 if(rc) {
385 dprintf(("DiveSetupBlitter returned %d", rc));
386 return(DD_OK);
387 }
388 sBlt.ulNumDstRects = DIVE_FULLY_VISIBLE;
389 sBlt.pVisDstRects = NULL;
390 memcpy(&dest->sBlt, &sBlt, sizeof(sBlt));
391 }
392 dprintf(("DiveBlitImage %x %d->%d", dest->hDive, src->diveBufNr, dest->diveBufNr));
393 rc = DiveBlitImage(dest->hDive, src->diveBufNr, dest->diveBufNr);
394 if(rc) {
395 dprintf(("DiveBlitImage returned %d", rc));
396 return(DD_OK);
397 }
398#ifdef PERFTEST
399 QueryPerformanceCounter(&liEnd);
400 if(liEnd.HighPart == liStart.HighPart) {
401 if(average == 0) {
402 average = (liEnd.LowPart - liStart.LowPart);
403 }
404 else average = (average + (liEnd.LowPart - liStart.LowPart))/2;
405 }
406#endif
407 SurfChangeUniquenessValue(dest);
408 return DD_OK;
409 }
410 }
411#endif
412
413 //TODO: do we need to check the source for clipping information in case
414 // the app wants to copy from the frame buffer?
415 if(dest->lpClipper)
416 {
417 DWORD rgnsize;
418 if(ClipGetClipList((IDirectDrawClipper*)dest->lpClipper, NULL, NULL, &rgnsize) == DD_OK)
419 {
420 LPRGNDATA lpRgnData = (LPRGNDATA)alloca(rgnsize);
421 if(lpRgnData == NULL) {
422 DebugInt3();
423 goto doblit;
424 }
425 if(ClipGetClipList((IDirectDrawClipper*)dest->lpClipper, NULL, lpRgnData, &rgnsize) == DD_OK)
426 {
427 RECT newdest, newsrc;
428 LPRECT lpClipRect = (LPRECT)&lpRgnData->Buffer;
429
430#ifdef PERFTEST
431 QueryPerformanceCounter(&liStart);
432#endif
433 for(i=0;i<lpRgnData->rdh.nCount;i++)
434 {
435 dprintf(("Clip list %d (%d,%d)(%d,%d)", i, lpClipRect[i].left, lpClipRect[i].bottom, lpClipRect[i].right, lpClipRect[i].top));
436
437 if(IntersectRect(&newdest, &DestRect, &lpClipRect[i]) == TRUE)
438 {
439 //TODO: This is not correct for stretching blits
440 if(lpSrcRect) {
441 newsrc.left = SrcRect.left + (newdest.left - DestRect.left);
442 newsrc.top = SrcRect.top + (newdest.top - DestRect.top);
443 newsrc.right = newsrc.left + RECT_WIDTH(&newdest);
444 newsrc.bottom = newsrc.top + RECT_HEIGHT(&newdest);
445 }
446// DDSURFACEDESC2 surfdesc = {0};
447// SurfLock4(dest, &newdest, &surfdesc, 0, 0);
448
449 ret = SurfDoBlt(This, &newdest, lpDDSrcSurface, (lpSrcRect) ? &newsrc : NULL, dwFlags, lpDDBltFx);
450 if(ret != DD_OK) {
451 break;
452 }
453// SurfUnlock(dest, surfdesc.lpSurface);
454 }
455 }
456#ifdef PERFTEST
457 if(liEnd.HighPart == liStart.HighPart) {
458 QueryPerformanceCounter(&liEnd);
459 if(average == 0) {
460 average = (liEnd.LowPart - liStart.LowPart);
461 }
462 else average = (average + (liEnd.LowPart - liStart.LowPart))/2;
463 }
464#endif
465
466 return ret;
467 }
468 }
469 }
470doblit:
471 return SurfDoBlt(This, &DestRect, lpDDSrcSurface, (lpSrcRect) ? &SrcRect : NULL, dwFlags, lpDDBltFx);
472}
473//******************************************************************************
474//******************************************************************************
475HRESULT WIN32API SurfDoBlt(THIS This, LPRECT lpDestRect, LPDIRECTDRAWSURFACE4 lpDDSrcSurface,
476 LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
477{
478 // We have determine between 3 different blit senarios.
479 // 1. Blitting between Divebuffers (Front/Backbuffer and primary surface)
480 // 2. Blitting between memory and Divebuffers (Front/Backbuffer and primary surface).
481 // 3. Blitting between memory buffers.
482 // 1 and 3 are easy. DiveBlitImage or memcpy will do the job for non transparent blits
483 // 2 is now also easy as we do colorconverion via Dive after each unlocking of a surface
484 // The advantage is that we don't have to call DiveSetupBlitter each time. The Blitter will be
485 // setup only when the screen resolution is changed by ddraw. I guess we should see a big performance
486 // increase by doing it this way, unless the software blits directly from memory to the primary surface)
487 // But even then this could be faster as the SetupBlitter call is timeconsumeing and DIVE does emulate
488 // the blit in SW anyway as there is no interface in the driver to blit with HW support from the sysmem.
489
490 OS2IDirectDrawSurface *dest = (OS2IDirectDrawSurface *)This;
491 OS2IDirectDrawSurface *src = (OS2IDirectDrawSurface *)lpDDSrcSurface;
492
493 int x, i, BlitWidth, BlitHeight;
494 char *pBltPos, *pSrcPos;
495 DDSURFACEDESC2 DestSurfaceDesc, SrcSurfaceDesc;
496 BOOL Found;
497 DWORD dwSrcColor, dwDestColor;
498
499 dprintf(("DDRAW: SurfDoBlt To Surf %08X, from Surf %08X\n",dest,src));
500 if ( (NULL!=lpDestRect)&& (NULL!=lpSrcRect))
501 dprintf(("DDRAW: SurfDoBlt to (%d,%d)(%d,%d) at %08X from (%d,%d)(%d,%d) at %08X\n", lpDestRect->left, lpDestRect->top,
502 lpDestRect->right, lpDestRect->bottom, dest, lpSrcRect->left, lpSrcRect->top,
503 lpSrcRect->right, lpSrcRect->bottom, src));
504
505 DestSurfaceDesc.dwSize = sizeof(DDSURFACEDESC2);
506 SrcSurfaceDesc.dwSize = sizeof(DDSURFACEDESC2);
507
508 // First check the simple first
509
510 dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC); // FIXME: can't handle right now
511
512 if(dwFlags & DDBLT_COLORFILL)
513 {
514 dprintf(("DDRAW: ColorFill\n"));
515 if((NULL==lpDDBltFx)||(lpDDBltFx->dwSize!=sizeof(DDBLTFX)) )
516 return DDERR_INVALIDPARAMS;
517
518 dest->DoColorFill(lpDestRect,lpDDBltFx->dwFillColor);
519
520 return(DD_OK); // according to the M$ DDK only one flag shall/can be set.
521 } // end of colorfill
522
523 if (dwFlags & DDBLT_DEPTHFILL)
524 {
525 dprintf(("DDRAW: DepthFill\n"));
526 #ifdef USE_OPENGL
527 GLboolean ztest;
528 // Todo support more than one Z-Buffer
529 // Clears the screen
530 dprintf(("DDRAW: Filling depth buffer with %ld\n", lpbltfx->b.dwFillDepth));
531 glClearDepth(lpDDBltFx->b.dwFillDepth / 65535.0); // We suppose a 16 bit Z Buffer
532 glGetBooleanv(GL_DEPTH_TEST, &ztest);
533 glDepthMask(GL_TRUE); // Enables Z writing to be sure to delete also the Z buffer
534 glClear(GL_DEPTH_BUFFER_BIT);
535 glDepthMask(ztest);
536
537 return (DD_OK);
538 #endif // USE_OPENGL
539 }
540
541 if(dwFlags & DDBLT_ROP)
542 {
543 // HEL and we only support the following ROPS
544 // SRC_COPY
545 // BLACKNESS
546 // WHITENESS
547 //
548 if(lpDDBltFx->dwROP & SRCCOPY)
549 dwFlags = 0; // srccopy is a normal fast blt
550 else
551 {
552 if(lpDDBltFx->dwROP & BLACKNESS)
553 {
554 if(1==dest->dwBytesPPDive)
555 {
556 // ToDo: Realy implement code to get the correct index for black in 8 Bitmode
557 dest->DoColorFill(lpDestRect, 0 );
558 }
559 else
560 dest->DoColorFill(lpDestRect, 0);
561 return DD_OK;
562 }
563
564 if(lpDDBltFx->dwROP & WHITENESS)
565 {
566 if(1==dest->dwBytesPPDive)
567 {
568 // ToDo: Realy implement code to get the correct index for white in 8 Bitmode
569 dest->DoColorFill(lpDestRect, 0xFFFFFFFF );
570 }
571 else
572 dest->DoColorFill(lpDestRect, 0xFFFFFFFF);
573 return (DD_OK);
574 }
575
576 return DDERR_NORASTEROPHW;
577 }
578 }
579
580 if(NULL==src)
581 {
582 dprintf(("DDRAW: Unsupported sourceless FX operation. Flags = 0x%04X\n",dwFlags));
583
584 return DD_OK;
585 }
586
587 if( ( (NULL==lpDestRect) && (NULL!=lpSrcRect) ) ||
588 ( (NULL==lpSrcRect) && (NULL!=lpDestRect) ) )
589 {
590 dprintf(("DDRAW: Blitting with scaling\n Not supported.\n"));
591
592 return DDERR_NOSTRETCHHW;
593 }
594
595 if( ( RECT_WIDTH(lpDestRect) != RECT_WIDTH(lpSrcRect) ) ||
596 ( RECT_HEIGHT(lpDestRect) != RECT_HEIGHT(lpSrcRect) )
597 )
598 {
599 // Stretching not supported
600 dprintf(("DDRAW: No stretched blits\n"));
601
602 return DDERR_NOSTRETCHHW;
603 }
604
605 if (dest->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
606 {
607 dprintf(("DDRAW: Dest is Primary Surface\n"));
608 if(src->DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
609 {
610 // special Type 1 : Bliting between parts of the screen
611
612 dprintf(("DDRAW: Src is Primary Surface\n"));
613
614 if( RECT_EQUAL(lpDestRect, lpSrcRect))
615 return DD_OK; // rects are the same => no blit needed
616
617 // Todo: might add transparent blits but I don't think they are used here, so later!
618
619 MoveRects( dest->pDiveBuffer,
620 lpDestRect,
621 lpSrcRect,
622 dest->dwBytesPPDive,
623 dest->dwPitchDB);
624 // MoveRects in framebuufer if we use colorconversion
625 if(dest->pFrameBuffer != dest->pDiveBuffer)
626 {
627 MoveRects( dest->pFrameBuffer,
628 lpDestRect,
629 lpSrcRect,
630 dest->lpDraw->GetScreenBpp()>>3,
631 dest->dwPitchFB);
632 }
633
634 // End of Special Type 1 blitting on the screen
635 }
636 else
637 {
638 if( src->diveBufNr>0)
639 {
640 dprintf(("DDRAW: DIVE Blit of all"));
641 if( (NULL==lpSrcRect)&&( NULL== lpDestRect))
642 {
643 // No Rectangles so use Dive to blit everything
644 // ToDo : Implement transparent blitting but that seams more
645 // inportant for partial blits.
646 // If we do this later we could skip this check and don't
647 // use Dive .This keeps our simpler and smaler
648 //
649 DiveBlitImage(dest->hDive, src->diveBufNr, dest->diveBufNr);
650
651//SvL: ???? shouldn't we return here?
652 SurfChangeUniquenessValue(dest);
653 return DD_OK;
654 }
655 }
656
657 // Everything else we do yourselfs
658 // Type 2 Sysmem to Primarysurface ca also be handled by this
659
660 if(!dwFlags)
661 {
662 dprintf(("DDRAW: Solid Blit\n"));
663
664 dest->BltSolid( dest->pDiveBuffer,
665 dest->pFrameBuffer,
666 lpDestRect->top,
667 lpDestRect->left,
668 dest->dwPitchDB,
669 dest->dwPitchFB,
670 src->pDiveBuffer,
671 src->pFrameBuffer,
672 lpSrcRect->top,
673 lpSrcRect->left,
674 RECT_WIDTH(lpDestRect),
675 RECT_HEIGHT(lpDestRect),
676 src->dwPitchDB,
677 src->dwPitchFB
678 );
679
680 }
681 else
682 {
683 pBltPos = (char*) dest->pDiveBuffer + (lpDestRect->top * dest->dwPitchDB) +
684 (lpDestRect->left * dest->dwBytesPPDive);
685
686 pSrcPos = (char*) src->pDiveBuffer + (lpSrcRect->top * src->dwPitchDB) +
687 (lpSrcRect->left * src->dwBytesPPDive);
688
689 BlitHeight = RECT_HEIGHT(lpDestRect);
690 BlitWidth = RECT_WIDTH(lpDestRect);
691 // Transparent Blit
692 if( (dwFlags &DDBLT_KEYSRC) || (dwFlags & DDBLT_KEYSRCOVERRIDE) )
693 {
694 dprintf(("DDRAW: Transparent src blit not done yet for primary!!"));
695 }
696 else
697 {
698 dprintf(("DDRAW: Unhandled Flags Destination colorkey ? 0x%04X",dwFlags));
699 }
700 }
701 } // end of handling blitting to primary
702 } // end of target primary surface
703 else
704 {
705 if(0==src->diveBufNr)
706 {
707 // copy from the screen to a buffer
708
709 if( (NULL==lpDestRect) &&
710 (NULL==lpSrcRect) &&
711 (dest->diveBufNr>0) )
712 {
713 // Blitting everything from frontbuffer to a Divebuffer
714 // ToDo: Might should add checking for flags here
715 DiveBlitImage(dest->hDive, src->diveBufNr, dest->diveBufNr);
716 }
717 else
718 {
719 // DIVE => DIVE or Mem => Dive
720 // or a rectangle from streen to a buffer can be handelt in the same way
721 pBltPos = (char*) dest->pDiveBuffer + (lpDestRect->top * dest->dwPitchDB) +
722 (lpDestRect->left * dest->dwBytesPPDive);
723
724 pSrcPos = (char*) src->pDiveBuffer + (lpSrcRect->top * src->dwPitchDB) +
725 (lpSrcRect->left * src->dwBytesPPDive);
726
727 BlitHeight = RECT_HEIGHT(lpDestRect);
728 BlitWidth = RECT_WIDTH(lpDestRect);
729
730 // Check for transparent blit
731 if(!dwFlags)
732 {
733 dest->BltSolid( dest->pDiveBuffer,
734 dest->pFrameBuffer,
735 lpDestRect->top,
736 lpDestRect->left,
737 dest->dwPitchDB,
738 dest->dwPitchFB,
739 src->pDiveBuffer,
740 src->pFrameBuffer,
741 lpSrcRect->top,
742 lpSrcRect->left,
743 RECT_WIDTH(lpDestRect),
744 RECT_HEIGHT(lpDestRect),
745 src->dwPitchDB,
746 src->dwPitchFB
747 );
748 }
749 else
750 {
751 dprintf(("DDRAW: Transblt not done yet"));
752 if(dwFlags & DDBLT_KEYSRC)
753 {
754 if(!(src->DDSurfaceDesc.dwFlags & DDCKEY_SRCBLT))
755 {
756 }
757 }
758 else
759 {
760 if(dwFlags & DDBLT_KEYSRCOVERRIDE)
761 {
762 }
763 else
764 {
765 }
766 }
767 }
768 }
769 } // end handling source screen
770 else
771 {
772 // DIVE => DIVE or Mem => Dive can be handelt in the same way
773
774 if( (src->pDiveBuffer == dest->pDiveBuffer) &&
775 (intersects(lpDestRect, lpSrcRect) ) )
776 {
777 // Overlapping rects on the same surface ?
778
779 // ToDo : Maybe implement all the fancy blit flags here too ? ;)
780
781 MoveRects( dest->pDiveBuffer,
782 lpDestRect,
783 lpSrcRect,
784 dest->dwBytesPPDive,
785 dest->dwPitchDB);
786
787 // MoveRects in framebuufer if we use colorconversion
788 if(dest->pFrameBuffer != dest->pDiveBuffer)
789 {
790 MoveRects( dest->pFrameBuffer,
791 lpDestRect,
792 lpSrcRect,
793 dest->lpDraw->GetScreenBpp()>>3,
794 dest->dwPitchFB);
795 }
796 return DD_OK;
797 }
798
799 // Check for transparent blit
800 if(!dwFlags)
801 {
802 dest->BltSolid( dest->pDiveBuffer,
803 dest->pFrameBuffer,
804 lpDestRect->top,
805 lpDestRect->left,
806 dest->dwPitchDB,
807 dest->dwPitchFB,
808 src->pDiveBuffer,
809 src->pFrameBuffer,
810 lpSrcRect->top,
811 lpSrcRect->left,
812 RECT_WIDTH(lpDestRect),
813 RECT_HEIGHT(lpDestRect),
814 src->dwPitchDB,
815 src->dwPitchFB
816 );
817 }
818 else
819 {
820 pBltPos = (char*) dest->pDiveBuffer + (lpDestRect->top * dest->dwPitchDB) +
821 (lpDestRect->left * dest->dwBytesPPDive);
822
823 pSrcPos = (char*) src->pDiveBuffer + (lpSrcRect->top * src->dwPitchDB) +
824 (lpSrcRect->left * src->dwBytesPPDive);
825
826 BlitHeight = RECT_HEIGHT(lpDestRect);
827 BlitWidth = RECT_WIDTH(lpDestRect);
828 DWORD dwPitch = dest->dwPitchDB;
829
830 if(dwFlags &DDBLT_ROTATIONANGLE)
831 {
832 return DDERR_NOROTATIONHW;
833 }
834
835 if(dwFlags & DDBLT_DDFX)
836 {
837 DWORD dwFx;
838
839 dwFlags &= ~DDBLT_DDFX; // remove the handled flag
840
841 if( NULL==lpDDBltFx)
842 return DDERR_INVALIDPARAMS;
843
844 dwFx = lpDDBltFx->dwDDFX;
845
846 // Remove unsupported Flags
847 dwFx &= ~(DDBLTFX_ARITHSTRETCHY | // Not streach support
848 DDBLTFX_ZBUFFERBASEDEST | // All ZBuffer flags are not
849 DDBLTFX_ZBUFFERRANGE | // implementet in M$ Dx 6
850 DDBLTFX_NOTEARING ); // No sync with VRetrace yet
851
852 if(dwFx & DDBLTFX_ROTATE180)
853 {
854 // 180 degree turn is a mix of a flip up/down and one left/right
855 dwFx |= (DDBLTFX_MIRRORUPDOWN | DDBLTFX_MIRRORLEFTRIGHT);
856 dwFx &= ~DDBLTFX_ROTATE180; // remove handled flag
857 }
858 if(dwFx & DDBLTFX_MIRRORUPDOWN)
859 {
860 // switching the the direction can be integrated with other flags
861 dwPitch = -dwPitch;
862 pBltPos = (char*) dest->pDiveBuffer +
863 ((lpDestRect->top +BlitHeight)* dest->dwPitchDB) +
864 (lpDestRect->left * dest->dwBytesPPDive);
865
866 dwFx &= ~DDBLTFX_MIRRORUPDOWN; // remove handled flag
867 }
868
869 if(dwFx & DDBLTFX_MIRRORLEFTRIGHT)
870 {
871 // 180 degree turn or a LR Mirroring
872 // don't support any other dwFlags like transparent at the moment
873
874 switch(dest->dwBytesPPDive)
875 {
876 case 1:
877 while(BlitHeight--)
878 {
879 x = BlitWidth;
880 while(x)
881 {
882 pBltPos[BlitWidth-x] = pSrcPos[x];
883 x--;
884 }
885 pBltPos += dwPitch;
886 pSrcPos += src->dwPitchDB;
887 }
888 break;
889 case 2:
890 while(BlitHeight--)
891 {
892 x = BlitWidth;
893 while(x)
894 {
895 ((USHORT*)pBltPos)[BlitWidth-x] = ((USHORT*)pSrcPos)[x];
896 x--;
897 }
898 pBltPos += dwPitch;
899 pSrcPos += src->dwPitchDB;
900 }
901 break;
902 case 3:
903 BlitWidth *= 3;
904 while(BlitHeight--)
905 {
906 x = BlitWidth;
907 while(x)
908 {
909 pBltPos[BlitWidth-x] = pSrcPos[x-2];
910 x--;
911 pBltPos[BlitWidth-x] = pSrcPos[x];
912 x--;
913 pBltPos[BlitWidth-x] = pSrcPos[x+2];
914 x--;
915 }
916 pBltPos += dwPitch;
917 pSrcPos += src->dwPitchDB;
918 }
919 break;
920 case 4:
921 while(BlitHeight--)
922 {
923 x = BlitWidth;
924 while(x)
925 {
926 ((DWORD*)pBltPos)[BlitWidth-x] = ((DWORD*)pSrcPos)[x];
927 x--;
928 }
929 pBltPos += dwPitch;
930 pSrcPos += src->dwPitchDB;
931 }
932 break;
933 } // end switch
934 SurfChangeUniquenessValue(dest);
935 return DD_OK;
936 }
937
938 if(dwFx)
939 _dump_DDBLTFX(dwFx);
940
941 // We ignore unhandled flags at the moment
942 }
943
944 if( (dwFlags & DDBLT_KEYSRC) |
945 (dwFlags & DDBLT_KEYSRCOVERRIDE) )
946 {
947 if(dwFlags & DDBLT_KEYSRCOVERRIDE)
948 {
949
950 if( NULL==lpDDBltFx)
951 return DDERR_INVALIDPARAMS;
952
953 dwFlags &= ~DDBLT_KEYSRCOVERRIDE;
954
955 // We work like the HEL and test only the low value
956 dwSrcColor = lpDDBltFx->ddckSrcColorkey.dwColorSpaceLowValue;
957
958 }
959 else
960 {
961
962 dwFlags &= ~DDBLT_KEYSRC;
963
964 // Not sure if that is OK maybe check if one is set ?
965 // if(!(src->DDSurfaceDesc.dwFlags & DDCKEY_SRCBLT)) return DDERR_WRONGPARAM;?
966
967 dwSrcColor = src->DDSurfaceDesc.ddckCKSrcBlt.dwColorSpaceLowValue;
968 }
969
970 // ToDo : We currently indicate that we don't support
971 // DDBLT_KEYDEST but HEL does change that!
972 // also add this key in the get/setColorKey functions
973
974 if( (dwFlags & DDBLT_KEYDEST) |
975 (dwFlags & DDBLT_KEYDESTOVERRIDE) )
976 {
977 // Source and dest color keying SLOW!!!
978 if(dwFlags & DDBLT_KEYDESTOVERRIDE)
979 {
980 if( NULL==lpDDBltFx)
981 return DDERR_INVALIDPARAMS;
982
983 dwFlags &= ~DDBLT_KEYDESTOVERRIDE;
984
985 // We work like the HEL and test only the low value
986 dwDestColor = lpDDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
987
988 }
989 else
990 {
991
992 dwFlags &= ~DDBLT_KEYDEST;
993
994 // Not sure if that is OK maybe check if one is set ?
995 // if(!(Dest->DDSurfaceDesc.dwFlags & DDCKEY_DESTBLT)) return DDERR_WRONGPARAM;?
996
997 dwDestColor = dest->DDSurfaceDesc.ddckCKDestBlt.dwColorSpaceLowValue;
998 }
999
1000 // This will be be slow maybe move to ASM ?
1001 // using MMX should be much faster
1002 switch(dest->dwBytesPPDive)
1003 {
1004 case 1:
1005 while(BlitHeight--)
1006 {
1007 x = 0;
1008 while(x<BlitWidth)
1009 {
1010 if(pSrcPos[x] != (char) dwSrcColor)
1011 {
1012 if(pBltPos[x] != (char) dwDestColor)
1013 pBltPos[x] = pSrcPos[x];
1014 }
1015 x++;
1016 }
1017 pBltPos += dwPitch;
1018 pSrcPos += src->dwPitchDB;
1019 }
1020 break;
1021 case 2:
1022 while(BlitHeight--)
1023 {
1024 x = 0;
1025 while(x<BlitWidth)
1026 {
1027 if(((USHORT*)pSrcPos)[x] != (USHORT) dwSrcColor)
1028 {
1029 if(((USHORT*)pBltPos)[x] != (USHORT) dwDestColor)
1030 ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
1031 }
1032 x++;
1033 }
1034 pBltPos += dwPitch;
1035 pSrcPos += src->dwPitchDB;
1036 }
1037 break;
1038 case 3:
1039 {
1040 char *pSC, *pDC;
1041 pSC = (char*)&dwSrcColor;
1042 pDC = (char*)&dwDestColor;
1043 BlitWidth *=3;
1044
1045 while(BlitHeight--)
1046 {
1047 x = 0;
1048
1049 while(x<BlitWidth)
1050 {
1051 if( (pSrcPos[x] != pSC[1]) &&
1052 (pSrcPos[x+1] != pSC[2]) &&
1053 (pSrcPos[x+2] != pSC[3])
1054 )
1055 {
1056 if( (pBltPos[x] != pDC[1]) &&
1057 (pBltPos[x+1] != pDC[2]) &&
1058 (pBltPos[x+2] != pDC[3])
1059 )
1060 {
1061 pBltPos[x] = pSrcPos[x];
1062 pBltPos[x+1] = pSrcPos[x+2];
1063 pBltPos[x+1] = pSrcPos[x+2];
1064 }
1065 }
1066 x +=3;
1067 }
1068 pBltPos += dwPitch;
1069 pSrcPos += src->dwPitchDB;
1070 }
1071 break;
1072 }
1073 case 4:
1074 while(BlitHeight--)
1075 {
1076 x = 0;
1077 while(x<BlitWidth)
1078 {
1079 if(((DWORD*)pSrcPos)[x] != dwSrcColor)
1080 {
1081 if(((DWORD*)pBltPos)[x] != dwDestColor)
1082 ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
1083 }
1084 x++;
1085 }
1086 pBltPos += dwPitch;
1087 pSrcPos += src->dwPitchDB;
1088 }
1089 break;
1090 } // End switch
1091 }
1092 else
1093 {
1094 // This will be be slow maybe move to ASM ?
1095 // using MMX should be much faster
1096 switch(dest->dwBytesPPDive)
1097 {
1098 case 1:
1099 while(BlitHeight--)
1100 {
1101 x = 0;
1102 while(x<BlitWidth)
1103 {
1104 if(pSrcPos[x] != (char) dwSrcColor)
1105 {
1106 pBltPos[x] = pSrcPos[x];
1107 }
1108 x++;
1109 }
1110 pBltPos += dwPitch;
1111 pSrcPos += src->dwPitchDB;
1112 }
1113 break;
1114 case 2:
1115 while(BlitHeight--)
1116 {
1117 x = 0;
1118 while(x<BlitWidth)
1119 {
1120 if(((USHORT*)pSrcPos)[x] != (USHORT) dwSrcColor)
1121 {
1122 ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
1123 }
1124 x++;
1125 }
1126 pBltPos += dwPitch;
1127 pSrcPos += src->dwPitchDB;
1128 }
1129 break;
1130 case 3:
1131 {
1132 char *pSC, *pDC;
1133 pSC = (char*)&dwSrcColor;
1134 pDC = (char*)&dwDestColor;
1135 BlitWidth *=3;
1136
1137 while(BlitHeight--)
1138 {
1139 x = 0;
1140
1141 while(x<BlitWidth)
1142 {
1143 if( (pSrcPos[x] != pSC[1]) &&
1144 (pSrcPos[x+1] != pSC[2]) &&
1145 (pSrcPos[x+2] != pSC[3])
1146 )
1147 {
1148 pBltPos[x] = pSrcPos[x];
1149 pBltPos[x+1] = pSrcPos[x+2];
1150 pBltPos[x+1] = pSrcPos[x+2];
1151 }
1152 x +=3;
1153 }
1154 pBltPos += dwPitch;
1155 pSrcPos += src->dwPitchDB;
1156 }
1157 break;
1158 }
1159 case 4:
1160 while(BlitHeight--)
1161 {
1162 x = 0;
1163 while(x<BlitWidth)
1164 {
1165 if(((DWORD*)pSrcPos)[x] != dwSrcColor)
1166 {
1167 ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
1168 }
1169 x++;
1170 }
1171 pBltPos += dwPitch;
1172 pSrcPos += src->dwPitchDB;
1173 }
1174 break;
1175 } // End switch
1176 // Only Source colorkey
1177 }
1178 SurfChangeUniquenessValue(dest);
1179 return DD_OK;
1180 }
1181
1182 if( (dwFlags & DDBLT_KEYDEST) |
1183 (dwFlags & DDBLT_KEYDESTOVERRIDE) )
1184 {
1185 // Dest color keying SLOW!!!
1186 if(dwFlags & DDBLT_KEYSRCOVERRIDE)
1187 {
1188 if( NULL==lpDDBltFx)
1189 return DDERR_INVALIDPARAMS;
1190
1191 dwFlags &= ~DDBLT_KEYSRCOVERRIDE;
1192
1193 // We work like the HEL and test only the low value
1194 dwDestColor = lpDDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
1195
1196 }
1197 else
1198 {
1199
1200 dwFlags &= ~DDBLT_KEYDEST;
1201
1202 // Not sure if that is OK maybe check if one is set ?
1203 // if(!(src->DDSurfaceDesc.dwFlags & DDCKEY_DESTBLT)) return DDERR_WRONGPARAM;?
1204
1205 dwDestColor = dest->DDSurfaceDesc.ddckCKDestBlt.dwColorSpaceLowValue;
1206 }
1207
1208 // This will be be slow maybe move to ASM ?
1209 // using MMX should be much faster
1210 switch(dest->dwBytesPPDive)
1211 {
1212 case 1:
1213 while(BlitHeight--)
1214 {
1215 x = 0;
1216 while(x<BlitWidth)
1217 {
1218 if(pBltPos[x] != (char) dwDestColor)
1219 pBltPos[x] = pSrcPos[x];
1220 x++;
1221 }
1222 pBltPos += dwPitch;
1223 pSrcPos += src->dwPitchDB;
1224 }
1225 break;
1226 case 2:
1227 while(BlitHeight--)
1228 {
1229 x = 0;
1230 while(x<BlitWidth)
1231 {
1232 if(((USHORT*)pBltPos)[x] != (USHORT) dwDestColor)
1233 ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
1234 x++;
1235 }
1236 pBltPos += dwPitch;
1237 pSrcPos += src->dwPitchDB;
1238 }
1239 break;
1240 case 3:
1241 {
1242 char *pSC, *pDC;
1243 pSC = (char*)&dwSrcColor;
1244 pDC = (char*)&dwDestColor;
1245 BlitWidth *=3;
1246
1247 while(BlitHeight--)
1248 {
1249 x = 0;
1250
1251 while(x<BlitWidth)
1252 {
1253 if( (pBltPos[x] != pDC[1]) &&
1254 (pBltPos[x+1] != pDC[2]) &&
1255 (pBltPos[x+2] != pDC[3])
1256 )
1257 {
1258 pBltPos[x] = pSrcPos[x];
1259 pBltPos[x+1] = pSrcPos[x+2];
1260 pBltPos[x+1] = pSrcPos[x+2];
1261 }
1262 x +=3;
1263 }
1264 pBltPos += dwPitch;
1265 pSrcPos += src->dwPitchDB;
1266 }
1267 break;
1268 }
1269 case 4:
1270 while(BlitHeight--)
1271 {
1272 x = 0;
1273 while(x<BlitWidth)
1274 {
1275 if( ((DWORD*)pBltPos)[x] != dwDestColor)
1276 ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
1277 x++;
1278 }
1279 pBltPos += dwPitch;
1280 pSrcPos += src->dwPitchDB;
1281 }
1282 break;
1283 } // End switch
1284 } // End of Dest ColorKey
1285
1286
1287 }// end handling dwFlags
1288 } // End handling source not Framebuffer
1289
1290 }// end handling destination not framebuffer
1291
1292 SurfChangeUniquenessValue(dest);
1293 return(DD_OK);
1294}
1295//******************************************************************************
1296//******************************************************************************
1297HRESULT WIN32API SurfBltBatch(THIS, LPDDBLTBATCH, DWORD, DWORD )
1298{
1299 dprintf(("DDRAW: SurfBltBatch Not implemented by M$\n"));
1300
1301 return(DD_OK);
1302}
1303//******************************************************************************
1304//******************************************************************************
1305HRESULT WIN32API SurfBltFast( THIS This ,
1306 DWORD dwX,
1307 DWORD dwY,
1308 LPDIRECTDRAWSURFACE2 lpDDSrcSurface,
1309 LPRECT lpSrcRect,
1310 DWORD dwTrans)
1311{
1312 dprintf(("DDRAW: SurfBltFast=>"));
1313 return SurfBltFast4( This,
1314 dwX,
1315 dwY,
1316 (LPDIRECTDRAWSURFACE4) lpDDSrcSurface,
1317 lpSrcRect,
1318 dwTrans);
1319}
1320//******************************************************************************
1321//******************************************************************************
1322HRESULT WIN32API SurfBltFast3(THIS This ,
1323 DWORD dwX,
1324 DWORD dwY,
1325 LPDIRECTDRAWSURFACE3 lpDDSrcSurface,
1326 LPRECT lpSrcRect,
1327 DWORD dwTrans)
1328{
1329 dprintf(("DDRAW: SurfBltFast3=>"));
1330 return SurfBltFast4( This,
1331 dwX,
1332 dwY,
1333 (LPDIRECTDRAWSURFACE4) lpDDSrcSurface,
1334 lpSrcRect,
1335 dwTrans);
1336}
1337//******************************************************************************
1338//******************************************************************************
1339HRESULT WIN32API SurfBltFast4( THIS This,
1340 DWORD dwX,
1341 DWORD dwY,
1342 LPDIRECTDRAWSURFACE4 lpDDSrcSurface,
1343 LPRECT lpSrcRect,
1344 DWORD dwTrans)
1345{
1346 OS2IDirectDrawSurface *dest = (OS2IDirectDrawSurface *)This;
1347 OS2IDirectDrawSurface *src = (OS2IDirectDrawSurface *)lpDDSrcSurface;
1348 RECTL SrcRect;
1349 char *pBltPos, *pSrcPos;
1350 DWORD dwDestColor, dwSrcColor, BlitWidth, BlitHeight, x;
1351
1352 dprintf(("DDRAW: SurfBltFast4 %08X at(%d/%d) onto %08X with flags %08X\n",src, dwX,dwY, dest, dwTrans));
1353
1354 if( (NULL == lpDDSrcSurface) ||
1355 ((LONG)dwX < 0) || ((LONG)dwY < 0) ||
1356 (dwX > dest->width) ||
1357 (dwY > dest->height))
1358 {
1359 dprintf(("DDRAW: Invalid Parameters %08X, %d %d", lpDDSrcSurface ,dest->width , dest->height));
1360 return DDERR_INVALIDPARAMS;
1361 }
1362
1363 if (NULL != lpSrcRect)
1364 {
1365 memcpy(&SrcRect,lpSrcRect,sizeof(RECTL) );
1366 }
1367 else
1368 {
1369 SrcRect.top = 0;
1370 SrcRect.left = 0;
1371 SrcRect.bottom = src->height;
1372 SrcRect.right = src->width;
1373 }
1374
1375 // Todo: Test for locked src/dest
1376
1377 pBltPos = (char*) dest->pDiveBuffer + (dwY * dest->dwPitchDB) +
1378 (dwX * dest->dwBytesPPDive);
1379
1380 pSrcPos = (char*) src->pDiveBuffer + (SrcRect.top * src->dwPitchDB) +
1381 (SrcRect.left * src->dwBytesPPDive);
1382
1383 BlitHeight = SrcRect.bottom - SrcRect.top;
1384 BlitWidth = (SrcRect.right - SrcRect.left) * src->dwBytesPPDive;
1385
1386 // Remove unsupported wait flag
1387 dwTrans &= ~DDBLTFAST_WAIT;
1388
1389 if(DDBLTFAST_NOCOLORKEY == dwTrans )
1390 {
1391 dprintf(( "Solid Blit, %d bits => %d bytes per line\n",
1392 (SrcRect.right - SrcRect.left),
1393 BlitWidth) );
1394 #ifdef USE_ASM
1395 BltRec(pBltPos, pSrcPos, BlitWidth, BlitHeight,
1396 dest->dwPitchDB,
1397 src->dwPitchDB);
1398 #else
1399 // Solid Blit
1400 while(1)
1401 {
1402 memcpy(pBltPos,pSrcPos,BlitWidth);
1403 pBltPos += dest->dwPitchDB;
1404 pSrcPos += src->dwPitchDB;
1405 if(! (--BlitHeight))
1406 break;
1407 }
1408 #endif
1409
1410 }
1411 else
1412 {
1413 dprintf(("DDRAW: TransBlit\n"));
1414
1415 if(dwTrans & DDBLTFAST_SRCCOLORKEY)
1416 {
1417 dprintf(("DDRAW: Trans SRC\n"));
1418 // transparent source
1419 dwSrcColor = src->DDSurfaceDesc.ddckCKSrcBlt.dwColorSpaceLowValue;
1420 if(dwTrans & DDBLTFAST_DESTCOLORKEY)
1421 {
1422 dprintf(("DDRAW: And Dest Colorkey"));
1423 dwDestColor = dest->DDSurfaceDesc.ddckCKDestBlt.dwColorSpaceLowValue;
1424 // Source and dest colorkeying
1425 switch(dest->dwBytesPPDive)
1426 {
1427 case 1:
1428 while(BlitHeight--)
1429 {
1430 x = 0;
1431 while(x<BlitWidth)
1432 {
1433 if(pSrcPos[x] != (char) dwSrcColor)
1434 {
1435 if(pBltPos[x] != (char) dwDestColor)
1436 pBltPos[x] = pSrcPos[x];
1437 }
1438 x++;
1439 }
1440 pBltPos += dest->dwPitchDB;
1441 pSrcPos += src->dwPitchDB;
1442 }
1443 break;
1444 case 2:
1445 while(BlitHeight--)
1446 {
1447 x = 0;
1448 while(x<BlitWidth)
1449 {
1450 if(((USHORT*)pSrcPos)[x] != (USHORT) dwSrcColor)
1451 {
1452 if(((USHORT*)pBltPos)[x] != (USHORT) dwDestColor)
1453 ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
1454 }
1455 x++;
1456 }
1457 pBltPos += dest->dwPitchDB;
1458 pSrcPos += src->dwPitchDB;
1459 }
1460 break;
1461 case 3:
1462 {
1463 char *pSC, *pDC;
1464 pSC = (char*)&dwSrcColor;
1465 pDC = (char*)&dwDestColor;
1466 BlitWidth *=3;
1467
1468 while(BlitHeight--)
1469 {
1470 x = 0;
1471
1472 while(x<BlitWidth)
1473 {
1474 if( (pSrcPos[x] != pSC[1]) &&
1475 (pSrcPos[x+1] != pSC[2]) &&
1476 (pSrcPos[x+2] != pSC[3])
1477 )
1478 {
1479 if( (pBltPos[x] != pDC[1]) &&
1480 (pBltPos[x+1] != pDC[2]) &&
1481 (pBltPos[x+2] != pDC[3])
1482 )
1483 {
1484 pBltPos[x] = pSrcPos[x];
1485 pBltPos[x+1] = pSrcPos[x+2];
1486 pBltPos[x+1] = pSrcPos[x+2];
1487 }
1488 }
1489 x +=3;
1490 }
1491 pBltPos += dest->dwPitchDB;
1492 pSrcPos += src->dwPitchDB;
1493 }
1494 break;
1495 }
1496 case 4:
1497 while(BlitHeight--)
1498 {
1499 x = 0;
1500 while(x<BlitWidth)
1501 {
1502 if(((DWORD*)pSrcPos)[x] != dwSrcColor)
1503 {
1504 if(((DWORD*)pBltPos)[x] != dwDestColor)
1505 ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
1506 }
1507 x++;
1508 }
1509 pBltPos += dest->dwPitchDB;
1510 pSrcPos += src->dwPitchDB;
1511 }
1512 break;
1513 } // End switch
1514 }
1515 else
1516 {
1517 // This MMX detection should be moved into OS2Draw
1518 // and into the surface constructor a setup for blitting pointers
1519 dprintf(("DDRAW: Only Src ColorKey"));
1520 switch(dest->dwBytesPPDive)
1521 {
1522 case 1:
1523 if (CPUHasMMX())
1524 while (BlitHeight--)
1525 {
1526 BlitColorKey8MMX((PBYTE)pBltPos,(PBYTE)pSrcPos,dwSrcColor,BlitWidth);
1527 pBltPos += dest->dwPitchDB;
1528 pSrcPos += src->dwPitchDB;
1529 }
1530 else
1531 while (BlitHeight--)
1532 {
1533 BlitColorKey8((PBYTE)pBltPos,(PBYTE)pSrcPos,dwSrcColor,BlitWidth);
1534 pBltPos += dest->dwPitchDB;
1535 pSrcPos += src->dwPitchDB;
1536 }
1537 break;
1538 case 2:
1539
1540 if (CPUHasMMX())
1541 while(BlitHeight--)
1542 {
1543 BlitColorKey16MMX((PBYTE)pBltPos,(PBYTE)pSrcPos,dwSrcColor,BlitWidth);
1544 pBltPos += dest->dwPitchDB;
1545 pSrcPos += src->dwPitchDB;
1546 }
1547 else
1548 while(BlitHeight--)
1549 {
1550 BlitColorKey16((PBYTE)pBltPos,(PBYTE)pSrcPos,dwSrcColor,BlitWidth);
1551 pBltPos += dest->dwPitchDB;
1552 pSrcPos += src->dwPitchDB;
1553 }
1554 break;
1555 case 3:
1556 char *pSC;
1557 pSC = (char*)&dwSrcColor;
1558 BlitWidth *=3;
1559
1560 while(BlitHeight--)
1561 {
1562 x = 0;
1563
1564 while(x<BlitWidth)
1565 {
1566 if( (pSrcPos[x] != pSC[1]) &&
1567 (pSrcPos[x+1] != pSC[2]) &&
1568 (pSrcPos[x+2] != pSC[3])
1569 )
1570 {
1571 pBltPos[x] = pSrcPos[x];
1572 pBltPos[x+1] = pSrcPos[x+1];
1573 pBltPos[x+1] = pSrcPos[x+2];
1574 }
1575 x +=3;
1576 }
1577 pBltPos += dest->dwPitchDB;
1578 pSrcPos += src->dwPitchDB;
1579 }
1580 break;
1581 case 4:
1582 break;
1583 }
1584 }
1585 }
1586 else
1587 {
1588 if (dwTrans & DDBLTFAST_DESTCOLORKEY)
1589 {
1590 dprintf(("DDRAW: DestColorKey\n"));
1591
1592 dwDestColor = dest->DDSurfaceDesc.ddckCKDestBlt.dwColorSpaceLowValue;
1593 switch(dest->dwBytesPPDive)
1594 {
1595 case 1:
1596 while(BlitHeight--)
1597 {
1598 x = 0;
1599 while(x<BlitWidth)
1600 {
1601 if(pBltPos[x] != (char) dwDestColor)
1602 pBltPos[x] = pSrcPos[x];
1603 x++;
1604 }
1605 pBltPos += dest->dwPitchDB;
1606 pSrcPos += src->dwPitchDB;
1607 }
1608 break;
1609 case 2:
1610 while(BlitHeight--)
1611 {
1612 x = 0;
1613 while(x<BlitWidth)
1614 {
1615 if(((USHORT*)pBltPos)[x] != (USHORT) dwDestColor)
1616 ((USHORT*)pBltPos)[x] = ((USHORT*)pSrcPos)[x];
1617 x++;
1618 }
1619 pBltPos += dest->dwPitchDB;
1620 pSrcPos += src->dwPitchDB;
1621 }
1622 break;
1623 case 3:
1624 {
1625 char *pSC, *pDC;
1626 pSC = (char*)&dwSrcColor;
1627 pDC = (char*)&dwDestColor;
1628 BlitWidth *=3;
1629
1630 while(BlitHeight--)
1631 {
1632 x = 0;
1633
1634 while(x<BlitWidth)
1635 {
1636 if( (pBltPos[x] != pDC[1]) &&
1637 (pBltPos[x+1] != pDC[2]) &&
1638 (pBltPos[x+2] != pDC[3])
1639 )
1640 {
1641 pBltPos[x] = pSrcPos[x];
1642 pBltPos[x+1] = pSrcPos[x+2];
1643 pBltPos[x+1] = pSrcPos[x+2];
1644 }
1645 x +=3;
1646 }
1647 pBltPos += dest->dwPitchDB;
1648 pSrcPos += src->dwPitchDB;
1649 }
1650 break;
1651 }
1652 case 4:
1653 while(BlitHeight--)
1654 {
1655 x = 0;
1656 while(x<BlitWidth)
1657 {
1658 if(((DWORD*)pBltPos)[x] != dwDestColor)
1659 ((DWORD*)pBltPos)[x] = ((DWORD*)pSrcPos)[x];
1660 x++;
1661 }
1662 pBltPos += dest->dwPitchDB;
1663 pSrcPos += src->dwPitchDB;
1664 }
1665 break;
1666 } // End switch
1667 }
1668 else
1669 {
1670 dprintf(("DDRAW: Unexpected Flags"));
1671 }
1672 }
1673 }
1674
1675 // if(dest->lpVtbl == dest->Vtbl4)
1676 // dest->Vtbl4->ChangeUniquenessValue(dest);
1677
1678 return DD_OK;
1679}
1680//******************************************************************************
1681//******************************************************************************
Note: See TracBrowser for help on using the repository browser.