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

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

Removed dependency on dive.dll. Load it on demand.

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