source: trunk/src/ddraw/surfblit.cpp@ 9566

Last change on this file since 9566 was 9566, checked in by sandervl, 23 years ago

Fixed pitch for offscreen surfaces so it doesn't conflict with GetDIBits/SetDIBits alignment; Use GetDIBits & SetDIBits with negative height. Origin must be top left

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