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

Last change on this file since 21483 was 21483, checked in by dmik, 15 years ago

ddraw: Don't define CINTERFACE twice.

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