1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: win32ss/gdi/dib/dib16bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 16bpp
6 * PROGRAMMERS: Jason Filby
7 * Thomas Bluemel
8 * Gregor Anich
9 * Doug Lyons
10 */
11
12 #include <win32k.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 #define DEC_OR_INC(var, decTrue, amount) \
18 ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
19
20 VOID
DIB_16BPP_PutPixel(SURFOBJ * SurfObj,LONG x,LONG y,ULONG c)21 DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
22 {
23 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
24 PWORD addr = (PWORD)byteaddr + x;
25
26 *addr = (WORD)c;
27 }
28
29 ULONG
DIB_16BPP_GetPixel(SURFOBJ * SurfObj,LONG x,LONG y)30 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
31 {
32 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
33 PWORD addr = (PWORD)byteaddr + x;
34 return (ULONG)(*addr);
35 }
36
37 VOID
DIB_16BPP_HLine(SURFOBJ * SurfObj,LONG x1,LONG x2,LONG y,ULONG c)38 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
39 {
40 PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1);
41
42 #if defined(_M_IX86) && !defined(_MSC_VER)
43 /* This is about 10% faster than the generic C code below */
44 LONG Count = x2 - x1;
45
46 __asm__ __volatile__ (
47 " cld\n"
48 " mov %0, %%eax\n"
49 " shl $16, %%eax\n"
50 " andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */
51 " or %0, %%eax\n"
52 " mov %2, %%edi\n"
53 " test $0x03, %%edi\n" /* Align to fullword boundary */
54 " jz 0f\n"
55 " stosw\n"
56 " dec %1\n"
57 " jz 1f\n"
58 "0:\n"
59 " mov %1,%%ecx\n" /* Setup count of fullwords to fill */
60 " shr $1,%%ecx\n"
61 " rep stosl\n" /* The actual fill */
62 " test $0x01, %1\n" /* One left to do at the right side? */
63 " jz 1f\n"
64 " stosw\n"
65 "1:\n"
66 : /* no output */
67 : "r"(c), "r"(Count), "m"(addr)
68 : "%eax", "%ecx", "%edi");
69 #else /* _M_IX86 */
70 LONG cx = x1;
71 DWORD cc;
72
73 if (0 != (cx & 0x01))
74 {
75 *((PWORD) addr) = (WORD)c;
76 cx++;
77 addr = (PDWORD)((PWORD)(addr) + 1);
78 }
79 cc = ((c & 0xffff) << 16) | (c & 0xffff);
80 while(cx + 1 < x2)
81 {
82 *addr++ = cc;
83 cx += 2;
84 }
85 if (cx < x2)
86 {
87 *((PWORD) addr) = (WORD)c;
88 }
89 #endif /* _M_IX86 */
90 }
91
92
93 VOID
DIB_16BPP_VLine(SURFOBJ * SurfObj,LONG x,LONG y1,LONG y2,ULONG c)94 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
95 {
96 #if defined(_M_IX86) && !defined(_MSC_VER)
97 asm volatile(
98 " testl %2, %2" "\n\t"
99 " jle 2f" "\n\t"
100 " movl %2, %%ecx" "\n\t"
101 " shrl $2, %2" "\n\t"
102 " andl $3, %%ecx" "\n\t"
103 " jz 1f" "\n\t"
104 "0:" "\n\t"
105 " movw %%ax, (%0)" "\n\t"
106 " addl %1, %0" "\n\t"
107 " decl %%ecx" "\n\t"
108 " jnz 0b" "\n\t"
109 " testl %2, %2" "\n\t"
110 " jz 2f" "\n\t"
111 "1:" "\n\t"
112 " movw %%ax, (%0)" "\n\t"
113 " addl %1, %0" "\n\t"
114 " movw %%ax, (%0)" "\n\t"
115 " addl %1, %0" "\n\t"
116 " movw %%ax, (%0)" "\n\t"
117 " addl %1, %0" "\n\t"
118 " movw %%ax, (%0)" "\n\t"
119 " addl %1, %0" "\n\t"
120 " decl %2" "\n\t"
121 " jnz 1b" "\n\t"
122 "2:" "\n\t"
123 : /* no output */
124 : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))),
125 "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c)
126 : "cc", "memory", "%ecx");
127 #else
128 PBYTE byteaddr = (PBYTE)(ULONG_PTR)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
129 PWORD addr = (PWORD)byteaddr + x;
130 LONG lDelta = SurfObj->lDelta;
131
132 byteaddr = (PBYTE)addr;
133 while(y1++ < y2)
134 {
135 *addr = (WORD)c;
136
137 byteaddr += lDelta;
138 addr = (PWORD)byteaddr;
139 }
140 #endif
141 }
142
143 BOOLEAN
DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)144 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
145 {
146 LONG i, j, sx, sy, xColor, f1;
147 PBYTE SourceBits, DestBits, SourceLine, DestLine;
148 PBYTE SourceBits_4BPP, SourceLine_4BPP;
149 PWORD Source32, Dest32;
150 DWORD Index, StartLeft, EndRight;
151 BOOLEAN bTopToBottom, bLeftToRight;
152
153 DPRINT("DIB_16BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
154 BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
155 BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
156 BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
157
158 /* Get back left to right flip here */
159 bLeftToRight = BltInfo->DestRect.left > BltInfo->DestRect.right;
160
161 /* Check for top to bottom flip needed. */
162 bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
163
164 DPRINT("BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
165 BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
166
167 /* Make WellOrdered with top < bottom and left < right */
168 RECTL_vMakeWellOrdered(&BltInfo->DestRect);
169
170 DPRINT("BPP is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
171 BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
172
173 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
174
175 switch(BltInfo->SourceSurface->iBitmapFormat)
176 {
177 case BMF_1BPP:
178 DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
179 BltInfo->DestRect.right - BltInfo->DestRect.left);
180 sx = BltInfo->SourcePoint.x;
181
182 /* This sets sy to the top line */
183 sy = BltInfo->SourcePoint.y;
184
185 if (bTopToBottom)
186 {
187 /* This sets sy to the bottom line */
188 sy += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
189 }
190
191 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
192 {
193 sx = BltInfo->SourcePoint.x;
194
195 if (bLeftToRight)
196 {
197 /* This sets the sx to the rightmost pixel */
198 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
199 StartLeft = BltInfo->DestRect.left + 1;
200 EndRight = BltInfo->DestRect.right + 1;
201 }
202 else
203 {
204 StartLeft = BltInfo->DestRect.left;
205 EndRight = BltInfo->DestRect.right;
206 }
207
208 for (i = StartLeft; i < EndRight; i++)
209 {
210 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
211 {
212 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
213 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
214 }
215 else
216 {
217 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
218 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
219 }
220 DEC_OR_INC(sx, bLeftToRight, 1);
221 }
222 DEC_OR_INC(sy, bTopToBottom, 1);
223 }
224 break;
225
226 case BMF_4BPP:
227 DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
228 BltInfo->DestRect.right - BltInfo->DestRect.left);
229
230 /* This sets SourceBits_4BPP to the top line */
231 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
232 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
233 (BltInfo->SourcePoint.x >> 1);
234
235 if (bTopToBottom)
236 {
237 /* This sets SourceBits_4BPP to the bottom line */
238 SourceBits_4BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
239 }
240
241 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
242 {
243 SourceLine_4BPP = SourceBits_4BPP;
244 sx = BltInfo->SourcePoint.x;
245 if (bLeftToRight)
246 {
247 /* This sets sx to the rightmost pixel */
248 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
249 }
250
251 f1 = sx & 1;
252
253 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
254 {
255 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
256 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
257 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
258 if(f1 == 1)
259 {
260 DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
261 f1 = 0;
262 }
263 else
264 {
265 f1 = 1;
266 }
267 DEC_OR_INC(sx, bLeftToRight, 1);
268 }
269 DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
270 }
271 break;
272
273 case BMF_8BPP:
274 DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
275 BltInfo->DestRect.right - BltInfo->DestRect.left);
276
277 /* This sets SourceLine to the top line */
278 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
279 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
280 BltInfo->SourcePoint.x;
281 DestLine = DestBits;
282
283 if (bTopToBottom)
284 {
285 /* This sets SourceLine to the bottom line */
286 SourceLine += BltInfo->SourceSurface->lDelta
287 * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
288 }
289
290 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
291 {
292 SourceBits = SourceLine;
293 DestBits = DestLine;
294
295 if (bLeftToRight)
296 {
297 /* This sets SourceBits to the rightmost pixel */
298 SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
299 }
300
301 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
302 {
303 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
304 BltInfo->XlateSourceToDest, *SourceBits);
305 DEC_OR_INC(SourceBits, bLeftToRight, 1);
306 DestBits += 2;
307 }
308 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
309 DestLine += BltInfo->DestSurface->lDelta;
310 }
311 break;
312
313 case BMF_16BPP:
314 DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
315 BltInfo->DestRect.right - BltInfo->DestRect.left);
316
317 DPRINT("BMF_16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
318 BltInfo->DestRect.left, BltInfo->DestRect.top,
319 BltInfo->DestRect.right, BltInfo->DestRect.bottom,
320 BltInfo->DestRect.right - BltInfo->DestRect.left);
321
322 if ((BltInfo->XlateSourceToDest == NULL ||
323 (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
324 (!bTopToBottom && !bLeftToRight))
325 {
326 DPRINT("XO_TRIVIAL is TRUE.\n");
327 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
328 {
329 /* This sets SourceBits to the top line */
330 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
331 (BltInfo->SourcePoint.y *
332 BltInfo->SourceSurface->lDelta) + 2 *
333 BltInfo->SourcePoint.x;
334
335 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
336 {
337 RtlMoveMemory(DestBits, SourceBits,
338 2 * (BltInfo->DestRect.right -
339 BltInfo->DestRect.left));
340
341 SourceBits += BltInfo->SourceSurface->lDelta;
342 DestBits += BltInfo->DestSurface->lDelta;
343 }
344 }
345 else
346 {
347 /* This sets SourceBits to the bottom line */
348 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
349 ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom -
350 BltInfo->DestRect.top - 1) *
351 BltInfo->SourceSurface->lDelta) + 2 *
352 BltInfo->SourcePoint.x;
353
354 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 +
355 ((BltInfo->DestRect.bottom - 1) *
356 BltInfo->DestSurface->lDelta) + 2 *
357 BltInfo->DestRect.left;
358
359 for (j = BltInfo->DestRect.bottom - 1;
360 BltInfo->DestRect.top <= j; j--)
361 {
362 RtlMoveMemory(DestBits, SourceBits, 2 *
363 (BltInfo->DestRect.right -
364 BltInfo->DestRect.left));
365
366 SourceBits -= BltInfo->SourceSurface->lDelta;
367 DestBits -= BltInfo->DestSurface->lDelta;
368 }
369 }
370 }
371 else
372 {
373 DPRINT("XO_TRIVIAL is NOT TRUE.\n");
374 if (!bTopToBottom && !bLeftToRight)
375 /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
376 {
377 DPRINT("Flip is None.\n");
378 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
379 {
380 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
381 (BltInfo->SourcePoint.y *
382 BltInfo->SourceSurface->lDelta) + 2 *
383 BltInfo->SourcePoint.x;
384
385 DestLine = DestBits;
386 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
387 {
388 SourceBits = SourceLine;
389 DestBits = DestLine;
390 for (i = BltInfo->DestRect.left; i <
391 BltInfo->DestRect.right; i++)
392 {
393 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
394 BltInfo->XlateSourceToDest,
395 *((WORD *)SourceBits));
396 SourceBits += 2;
397 DestBits += 2;
398 }
399 SourceLine += BltInfo->SourceSurface->lDelta;
400 DestLine += BltInfo->DestSurface->lDelta;
401 }
402 }
403 else
404 {
405 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
406 ((BltInfo->SourcePoint.y +
407 BltInfo->DestRect.bottom -
408 BltInfo->DestRect.top - 1) *
409 BltInfo->SourceSurface->lDelta) + 2 *
410 BltInfo->SourcePoint.x;
411
412 DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
413 ((BltInfo->DestRect.bottom - 1) *
414 BltInfo->DestSurface->lDelta) + 2 *
415 BltInfo->DestRect.left;
416
417 for (j = BltInfo->DestRect.bottom - 1;
418 BltInfo->DestRect.top <= j; j--)
419 {
420 SourceBits = SourceLine;
421 DestBits = DestLine;
422 for (i = BltInfo->DestRect.left; i <
423 BltInfo->DestRect.right; i++)
424 {
425 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
426 BltInfo->XlateSourceToDest,
427 *((WORD *)SourceBits));
428 SourceBits += 2;
429 DestBits += 2;
430 }
431 SourceLine -= BltInfo->SourceSurface->lDelta;
432 DestLine -= BltInfo->DestSurface->lDelta;
433 }
434 }
435 }
436 else
437 {
438 /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
439 BOOL TopToBottomDone = FALSE;
440
441 if (bLeftToRight)
442 {
443 DPRINT("Flip is bLeftToRight.\n");
444
445 /* Allocate enough pixels for a row in WORD's */
446 WORD *store = ExAllocatePoolWithTag(NonPagedPool,
447 (BltInfo->DestRect.right - BltInfo->DestRect.left + 1) * 2, TAG_DIB);
448 if (store == NULL)
449 {
450 DPRINT1("Storage Allocation Failed.\n");
451 return FALSE;
452 }
453 WORD Index;
454
455 /* This sets SourceBits to the bottom line */
456 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
457 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
458 * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
459
460 /* Sets DestBits to the bottom line */
461 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
462 + (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
463 + 2 * BltInfo->DestRect.left + 2;
464
465 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
466 {
467 /* Set Dest32 to right pixel */
468 Dest32 = (WORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
469 Source32 = (WORD *) SourceBits;
470
471 Index = 0;
472
473 /* Store pixels from left to right */
474 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
475 {
476 store[Index] = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *(WORD *)Source32++);
477 Index++;
478 }
479
480 Index = 0;
481
482 /* Copy stored data to pixels from right to left */
483 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
484 {
485 *(WORD *)Dest32-- = store[Index];
486 Index++;
487 }
488
489 SourceBits -= BltInfo->SourceSurface->lDelta;
490 DestBits -= BltInfo->DestSurface->lDelta;
491 }
492 ExFreePoolWithTag(store, TAG_DIB);
493 TopToBottomDone = TRUE;
494 }
495
496 if (bTopToBottom)
497 {
498 DPRINT("Flip is bTopToBottom.\n");
499
500 /* Allocate enough pixels for a column in WORD's */
501 WORD *store = ExAllocatePoolWithTag(NonPagedPool,
502 (BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1) * 2, TAG_DIB);
503 if (store == NULL)
504 {
505 DPRINT1("Storage Allocation Failed.\n");
506 return FALSE;
507 }
508
509 /* This set SourceBits to the top line */
510 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
511 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
512 + 2 * BltInfo->SourcePoint.x;
513
514 /* This sets DestBits to the top line */
515 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
516 + ((BltInfo->DestRect.top) * BltInfo->DestSurface->lDelta)
517 + 2 * BltInfo->DestRect.left;
518
519 if ((BltInfo->SourceSurface->fjBitmap & BMF_TOPDOWN) == 0)
520 {
521 DestBits += BltInfo->DestSurface->lDelta;
522 }
523
524 if (bLeftToRight)
525 {
526 DPRINT("Adjusting DestBits for bLeftToRight.\n");
527 DestBits += 2;
528 }
529
530 /* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
531 * and have already completed the bLeftToRight. So we will lose our first flip output
532 * unless we work with its output which is at the destination site. So in this case
533 * our new Source becomes the previous outputs Destination. */
534
535 if (TopToBottomDone)
536 {
537 /* This sets SourceBits to the top line */
538 SourceBits = DestBits;
539 }
540
541 for (j = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= j ; j--)
542 {
543 /* Set Dest32 to bottom pixel */
544 Dest32 = (WORD *) DestBits + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
545 * BltInfo->DestSurface->lDelta / 2;
546 Source32 = (WORD *) SourceBits;
547
548 Index = 0;
549
550 /* Store pixels from top to bottom */
551 for (i = BltInfo->DestRect.top; i <= BltInfo->DestRect.bottom - 1; i++)
552 {
553 store[Index] = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32);
554 Source32 += BltInfo->SourceSurface->lDelta / 2;
555 Index++;
556 }
557
558 Index = 0;
559
560 /* Copy stored data to pixels from bottom to top */
561 for (i = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= i; i--)
562 {
563 *Dest32 = store[Index];
564 Dest32 -= BltInfo->DestSurface->lDelta / 2;
565 Index++;
566 }
567 SourceBits += 2;
568 DestBits += 2;
569 }
570 ExFreePoolWithTag(store, TAG_DIB);
571 }
572
573 }
574 }
575 break;
576
577 case BMF_24BPP:
578
579 DPRINT("BMF_24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
580 BltInfo->DestRect.left, BltInfo->DestRect.top,
581 BltInfo->DestRect.right, BltInfo->DestRect.bottom,
582 BltInfo->DestRect.right - BltInfo->DestRect.left);
583
584 /* This sets SourceLine to the top line */
585 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
586 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
587 3 * BltInfo->SourcePoint.x;
588
589 if (bTopToBottom)
590 {
591 /* This sets SourceLine to the bottom line */
592 SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
593 }
594 DestLine = DestBits;
595
596 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
597 {
598 SourceBits = SourceLine;
599 DestBits = DestLine;
600
601 if (bLeftToRight)
602 {
603 /* This sets the SourceBits to the rightmost pixel */
604 SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
605 }
606 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
607 {
608 xColor = (*(SourceBits + 2) << 0x10) +
609 (*(SourceBits + 1) << 0x08) + (*(SourceBits));
610
611 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
612 BltInfo->XlateSourceToDest, xColor);
613
614 DEC_OR_INC(SourceBits, bLeftToRight, 3);
615 DestBits += 2;
616 }
617 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
618 DestLine += BltInfo->DestSurface->lDelta;
619 }
620 break;
621
622 case BMF_32BPP:
623 DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
624 BltInfo->DestRect.right - BltInfo->DestRect.left);
625
626 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
627 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
628 4 * BltInfo->SourcePoint.x;
629
630 if (bTopToBottom)
631 {
632 /* This sets SourceLine to the bottom line */
633 SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
634 }
635 DestLine = DestBits;
636
637 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
638 {
639 SourceBits = SourceLine;
640 DestBits = DestLine;
641
642 if (bLeftToRight)
643 {
644 /* This sets SourceBits to the rightmost pixel */
645 SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
646 }
647
648 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
649 {
650 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
651 BltInfo->XlateSourceToDest,
652 *((PDWORD) SourceBits));
653 DEC_OR_INC(SourceBits, bLeftToRight, 4);
654 DestBits += 2;
655 }
656
657 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
658 DestLine += BltInfo->DestSurface->lDelta;
659 }
660 break;
661
662 default:
663 DPRINT1("DIB_16BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n",
664 BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
665 return FALSE;
666 }
667
668 return TRUE;
669 }
670
671 /* Optimize for bitBlt */
672 BOOLEAN
DIB_16BPP_ColorFill(SURFOBJ * DestSurface,RECTL * DestRect,ULONG color)673 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
674 {
675 LONG DestY;
676
677 /* Make WellOrdered with top < bottom and left < right */
678 RECTL_vMakeWellOrdered(DestRect);
679
680 #if defined(_M_IX86) && !defined(_MSC_VER)
681 /* This is about 10% faster than the generic C code below */
682 ULONG delta = DestSurface->lDelta;
683 ULONG width = (DestRect->right - DestRect->left) ;
684 PULONG pos = (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1));
685 color = (color&0xffff); /* If the color value is "abcd", put "abcdabcd" into color */
686 color += (color<<16);
687
688 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
689 {
690 __asm__ __volatile__ (
691 "cld\n\t"
692 "mov %1,%%ebx\n\t"
693 "mov %2,%%edi\n\t"
694 "test $0x03, %%edi\n\t" /* Align to fullword boundary */
695 "jz 1f\n\t"
696 "stosw\n\t"
697 "dec %%ebx\n\t"
698 "jz 2f\n"
699 "1:\n\t"
700 "mov %%ebx,%%ecx\n\t" /* Setup count of fullwords to fill */
701 "shr $1,%%ecx\n\t"
702 "rep stosl\n\t" /* The actual fill */
703 "test $0x01, %%ebx\n\t" /* One left to do at the right side? */
704 "jz 2f\n\t"
705 "stosw\n"
706 "2:"
707 :
708 : "a" (color), "r" (width), "m" (pos)
709 : "%ecx", "%ebx", "%edi");
710 pos =(PULONG)((ULONG_PTR)pos + delta);
711 }
712 #else /* _M_IX86 */
713
714 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
715 {
716 DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
717 }
718 #endif
719 return TRUE;
720 }
721
722 BOOLEAN
DIB_16BPP_TransparentBlt(SURFOBJ * DestSurf,SURFOBJ * SourceSurf,RECTL * DestRect,RECTL * SourceRect,XLATEOBJ * ColorTranslation,ULONG iTransColor)723 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
724 RECTL* DestRect, RECTL *SourceRect,
725 XLATEOBJ *ColorTranslation, ULONG iTransColor)
726 {
727 LONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, wd;
728 ULONG *DestBits, Source, Dest;
729
730 LONG DstHeight;
731 LONG DstWidth;
732 LONG SrcHeight;
733 LONG SrcWidth;
734
735 DstHeight = DestRect->bottom - DestRect->top;
736 DstWidth = DestRect->right - DestRect->left;
737 SrcHeight = SourceRect->bottom - SourceRect->top;
738 SrcWidth = SourceRect->right - SourceRect->left;
739
740 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
741 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
742 (DestRect->left << 1) +
743 DestRect->top * DestSurf->lDelta);
744 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
745
746 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
747 {
748 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
749 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
750 {
751 Dest = *DestBits;
752
753 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
754 if (SourceX >= 0 && SourceY >= 0 &&
755 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
756 {
757 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
758 if(Source != iTransColor)
759 {
760 Dest &= 0xFFFF0000;
761 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
762 }
763 }
764
765 SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth;
766 if (SourceX >= 0 && SourceY >= 0 &&
767 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
768 {
769 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
770 if(Source != iTransColor)
771 {
772 Dest &= 0xFFFF;
773 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
774 }
775 }
776
777 *DestBits = Dest;
778 }
779
780 if(X < DestRect->right)
781 {
782 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
783 if (SourceX >= 0 && SourceY >= 0 &&
784 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
785 {
786 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
787 if(Source != iTransColor)
788 {
789 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation,
790 Source);
791 }
792 }
793
794 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
795 }
796
797 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
798 }
799
800 return TRUE;
801 }
802
803 typedef union
804 {
805 ULONG ul;
806 struct
807 {
808 UCHAR red;
809 UCHAR green;
810 UCHAR blue;
811 UCHAR alpha;
812 } col;
813 } NICEPIXEL32;
814
815 typedef union
816 {
817 USHORT us;
818 struct
819 {
820 USHORT blue :5;
821 USHORT green :6;
822 USHORT red :5;
823 } col;
824 } NICEPIXEL16_565;
825
826 typedef union
827 {
828 USHORT us;
829 struct
830 {
831 USHORT blue :5;
832 USHORT green :5;
833 USHORT red :5;
834 USHORT xxxx :1;
835 } col;
836 } NICEPIXEL16_555;
837
838 static __inline UCHAR
Clamp6(ULONG val)839 Clamp6(ULONG val)
840 {
841 return (val > 63) ? 63 : (UCHAR)val;
842 }
843
844 static __inline UCHAR
Clamp5(ULONG val)845 Clamp5(ULONG val)
846 {
847 return (val > 31) ? 31 : (UCHAR)val;
848 }
849
850 BOOLEAN
DIB_16BPP_AlphaBlend(SURFOBJ * Dest,SURFOBJ * Source,RECTL * DestRect,RECTL * SourceRect,CLIPOBJ * ClipRegion,XLATEOBJ * ColorTranslation,BLENDOBJ * BlendObj)851 DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
852 RECTL* SourceRect, CLIPOBJ* ClipRegion,
853 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
854 {
855 INT DstX, DstY, SrcX, SrcY;
856 BLENDFUNCTION BlendFunc;
857 NICEPIXEL32 SrcPixel32;
858 UCHAR Alpha;
859 EXLATEOBJ* pexlo;
860 EXLATEOBJ exloSrcRGB;
861
862 DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
863 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
864 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
865
866 BlendFunc = BlendObj->BlendFunction;
867 if (BlendFunc.BlendOp != AC_SRC_OVER)
868 {
869 DPRINT1("BlendOp != AC_SRC_OVER\n");
870 return FALSE;
871 }
872 if (BlendFunc.BlendFlags != 0)
873 {
874 DPRINT1("BlendFlags != 0\n");
875 return FALSE;
876 }
877 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
878 {
879 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
880 return FALSE;
881 }
882 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
883 (BitsPerFormat(Source->iBitmapFormat) != 32))
884 {
885 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
886 return FALSE;
887 }
888
889 if (!ColorTranslation)
890 {
891 DPRINT1("ColorTranslation must not be NULL!\n");
892 return FALSE;
893 }
894
895 pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
896 EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0);
897
898 if (pexlo->ppalDst->flFlags & PAL_RGB16_555)
899 {
900 NICEPIXEL16_555 DstPixel16;
901
902 SrcY = SourceRect->top;
903 DstY = DestRect->top;
904 while ( DstY < DestRect->bottom )
905 {
906 SrcX = SourceRect->left;
907 DstX = DestRect->left;
908 while(DstX < DestRect->right)
909 {
910 SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo);
911 SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255;
912 SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255;
913 SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255;
914
915 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
916 (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
917 BlendFunc.SourceConstantAlpha;
918
919 Alpha >>= 3;
920
921 DstPixel16.us = DIB_16BPP_GetPixel(Dest, DstX, DstY) & 0xFFFF;
922 /* Perform bit loss */
923 SrcPixel32.col.red >>= 3;
924 SrcPixel32.col.green >>= 3;
925 SrcPixel32.col.blue >>= 3;
926
927 /* Do the blend in the right bit depth */
928 DstPixel16.col.red = Clamp5((DstPixel16.col.red * (31 - Alpha)) / 31 + SrcPixel32.col.red);
929 DstPixel16.col.green = Clamp5((DstPixel16.col.green * (31 - Alpha)) / 31 + SrcPixel32.col.green);
930 DstPixel16.col.blue = Clamp5((DstPixel16.col.blue * (31 - Alpha)) / 31 + SrcPixel32.col.blue);
931
932 DIB_16BPP_PutPixel(Dest, DstX, DstY, DstPixel16.us);
933
934 DstX++;
935 SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left))
936 /(DestRect->right-DestRect->left);
937 }
938 DstY++;
939 SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top))
940 /(DestRect->bottom-DestRect->top);
941 }
942 }
943 else
944 {
945 NICEPIXEL16_565 DstPixel16;
946 UCHAR Alpha6, Alpha5;
947
948 SrcY = SourceRect->top;
949 DstY = DestRect->top;
950 while ( DstY < DestRect->bottom )
951 {
952 SrcX = SourceRect->left;
953 DstX = DestRect->left;
954 while(DstX < DestRect->right)
955 {
956 SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo);
957 SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255;
958 SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255;
959 SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255;
960
961 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
962 (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
963 BlendFunc.SourceConstantAlpha;
964
965 Alpha6 = Alpha >> 2;
966 Alpha5 = Alpha >> 3;
967
968 DstPixel16.us = DIB_16BPP_GetPixel(Dest, DstX, DstY) & 0xFFFF;
969 /* Perform bit loss */
970 SrcPixel32.col.red >>= 3;
971 SrcPixel32.col.green >>= 2;
972 SrcPixel32.col.blue >>= 3;
973
974 /* Do the blend in the right bit depth */
975 DstPixel16.col.red = Clamp5((DstPixel16.col.red * (31 - Alpha5)) / 31 + SrcPixel32.col.red);
976 DstPixel16.col.green = Clamp6((DstPixel16.col.green * (63 - Alpha6)) / 63 + SrcPixel32.col.green);
977 DstPixel16.col.blue = Clamp5((DstPixel16.col.blue * (31 - Alpha5)) / 31 + SrcPixel32.col.blue);
978
979 DIB_16BPP_PutPixel(Dest, DstX, DstY, DstPixel16.us);
980
981 DstX++;
982 SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left))
983 /(DestRect->right-DestRect->left);
984 }
985 DstY++;
986 SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top))
987 /(DestRect->bottom-DestRect->top);
988 }
989 }
990
991 EXLATEOBJ_vCleanup(&exloSrcRGB);
992
993 return TRUE;
994 }
995
996 /* EOF */
997