Sync with trunk.
[reactos.git] / win32ss / gdi / dib / dib16bpp.c
1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/dib/dib16bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 16bpp
6 * PROGRAMMERS: Jason Filby
7 * Thomas Bluemel
8 * Gregor Anich
9 */
10
11 #include <win32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 VOID
17 DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
18 {
19 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
20 PWORD addr = (PWORD)byteaddr + x;
21
22 *addr = (WORD)c;
23 }
24
25 ULONG
26 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
27 {
28 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
29 PWORD addr = (PWORD)byteaddr + x;
30 return (ULONG)(*addr);
31 }
32
33 VOID
34 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
35 {
36 PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1);
37
38 #if defined(_M_IX86) && !defined(_MSC_VER)
39 /* This is about 10% faster than the generic C code below */
40 LONG Count = x2 - x1;
41
42 __asm__ __volatile__ (
43 " cld\n"
44 " mov %0, %%eax\n"
45 " shl $16, %%eax\n"
46 " andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */
47 " or %0, %%eax\n"
48 " mov %2, %%edi\n"
49 " test $0x03, %%edi\n" /* Align to fullword boundary */
50 " jz 0f\n"
51 " stosw\n"
52 " dec %1\n"
53 " jz 1f\n"
54 "0:\n"
55 " mov %1,%%ecx\n" /* Setup count of fullwords to fill */
56 " shr $1,%%ecx\n"
57 " rep stosl\n" /* The actual fill */
58 " test $0x01, %1\n" /* One left to do at the right side? */
59 " jz 1f\n"
60 " stosw\n"
61 "1:\n"
62 : /* no output */
63 : "r"(c), "r"(Count), "m"(addr)
64 : "%eax", "%ecx", "%edi");
65 #else /* _M_IX86 */
66 LONG cx = x1;
67 DWORD cc;
68
69 if (0 != (cx & 0x01))
70 {
71 *((PWORD) addr) = (WORD)c;
72 cx++;
73 addr = (PDWORD)((PWORD)(addr) + 1);
74 }
75 cc = ((c & 0xffff) << 16) | (c & 0xffff);
76 while(cx + 1 < x2)
77 {
78 *addr++ = cc;
79 cx += 2;
80 }
81 if (cx < x2)
82 {
83 *((PWORD) addr) = (WORD)c;
84 }
85 #endif /* _M_IX86 */
86 }
87
88
89 VOID
90 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
91 {
92 #if defined(_M_IX86) && !defined(_MSC_VER)
93 asm volatile(
94 " testl %2, %2" "\n\t"
95 " jle 2f" "\n\t"
96 " movl %2, %%ecx" "\n\t"
97 " shrl $2, %2" "\n\t"
98 " andl $3, %%ecx" "\n\t"
99 " jz 1f" "\n\t"
100 "0:" "\n\t"
101 " movw %%ax, (%0)" "\n\t"
102 " addl %1, %0" "\n\t"
103 " decl %%ecx" "\n\t"
104 " jnz 0b" "\n\t"
105 " testl %2, %2" "\n\t"
106 " jz 2f" "\n\t"
107 "1:" "\n\t"
108 " movw %%ax, (%0)" "\n\t"
109 " addl %1, %0" "\n\t"
110 " movw %%ax, (%0)" "\n\t"
111 " addl %1, %0" "\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 " decl %2" "\n\t"
117 " jnz 1b" "\n\t"
118 "2:" "\n\t"
119 : /* no output */
120 : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))),
121 "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c)
122 : "cc", "memory", "%ecx");
123 #else
124 PBYTE byteaddr = (PBYTE)(ULONG_PTR)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
125 PWORD addr = (PWORD)byteaddr + x;
126 LONG lDelta = SurfObj->lDelta;
127
128 byteaddr = (PBYTE)addr;
129 while(y1++ < y2)
130 {
131 *addr = (WORD)c;
132
133 byteaddr += lDelta;
134 addr = (PWORD)byteaddr;
135 }
136 #endif
137 }
138
139 BOOLEAN
140 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
141 {
142 LONG i, j, sx, sy, xColor, f1;
143 PBYTE SourceBits, DestBits, SourceLine, DestLine;
144 PBYTE SourceBits_4BPP, SourceLine_4BPP;
145 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
146
147 switch(BltInfo->SourceSurface->iBitmapFormat)
148 {
149 case BMF_1BPP:
150 sx = BltInfo->SourcePoint.x;
151 sy = BltInfo->SourcePoint.y;
152 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
153 {
154 sx = BltInfo->SourcePoint.x;
155 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
156 {
157 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
158 {
159 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
160 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
161 }
162 else
163 {
164 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
165 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
166 }
167 sx++;
168 }
169 sy++;
170 }
171 break;
172
173 case BMF_4BPP:
174 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
175 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
176 (BltInfo->SourcePoint.x >> 1);
177
178 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
179 {
180 SourceLine_4BPP = SourceBits_4BPP;
181 sx = BltInfo->SourcePoint.x;
182 f1 = sx & 1;
183
184 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
185 {
186 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
187 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
188 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
189 if(f1 == 1)
190 {
191 SourceLine_4BPP++;
192 f1 = 0;
193 }
194 else
195 {
196 f1 = 1;
197 }
198 sx++;
199 }
200 SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
201 }
202 break;
203
204 case BMF_8BPP:
205 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
206 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
207 BltInfo->SourcePoint.x;
208 DestLine = DestBits;
209
210 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
211 {
212 SourceBits = SourceLine;
213 DestBits = DestLine;
214
215 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
216 {
217 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
218 BltInfo->XlateSourceToDest, *SourceBits);
219 SourceBits += 1;
220 DestBits += 2;
221 }
222
223 SourceLine += BltInfo->SourceSurface->lDelta;
224 DestLine += BltInfo->DestSurface->lDelta;
225 }
226 break;
227
228 case BMF_16BPP:
229 if (NULL == BltInfo->XlateSourceToDest || 0 !=
230 (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
231 {
232 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
233 {
234 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
235 (BltInfo->SourcePoint.y *
236 BltInfo->SourceSurface->lDelta) + 2 *
237 BltInfo->SourcePoint.x;
238
239 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
240 {
241 RtlMoveMemory(DestBits, SourceBits,
242 2 * (BltInfo->DestRect.right -
243 BltInfo->DestRect.left));
244
245 SourceBits += BltInfo->SourceSurface->lDelta;
246 DestBits += BltInfo->DestSurface->lDelta;
247 }
248 }
249 else
250 {
251 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
252 ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom -
253 BltInfo->DestRect.top - 1) *
254 BltInfo->SourceSurface->lDelta) + 2 *
255 BltInfo->SourcePoint.x;
256
257 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 +
258 ((BltInfo->DestRect.bottom - 1) *
259 BltInfo->DestSurface->lDelta) + 2 *
260 BltInfo->DestRect.left;
261
262 for (j = BltInfo->DestRect.bottom - 1;
263 BltInfo->DestRect.top <= j; j--)
264 {
265 RtlMoveMemory(DestBits, SourceBits, 2 *
266 (BltInfo->DestRect.right -
267 BltInfo->DestRect.left));
268
269 SourceBits -= BltInfo->SourceSurface->lDelta;
270 DestBits -= BltInfo->DestSurface->lDelta;
271 }
272 }
273 }
274 else
275 {
276 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
277 {
278 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
279 (BltInfo->SourcePoint.y *
280 BltInfo->SourceSurface->lDelta) + 2 *
281 BltInfo->SourcePoint.x;
282
283 DestLine = DestBits;
284 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
285 {
286 SourceBits = SourceLine;
287 DestBits = DestLine;
288 for (i = BltInfo->DestRect.left; i <
289 BltInfo->DestRect.right; i++)
290 {
291 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
292 BltInfo->XlateSourceToDest,
293 *((WORD *)SourceBits));
294 SourceBits += 2;
295 DestBits += 2;
296 }
297 SourceLine += BltInfo->SourceSurface->lDelta;
298 DestLine += BltInfo->DestSurface->lDelta;
299 }
300 }
301 else
302 {
303 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
304 ((BltInfo->SourcePoint.y +
305 BltInfo->DestRect.bottom -
306 BltInfo->DestRect.top - 1) *
307 BltInfo->SourceSurface->lDelta) + 2 *
308 BltInfo->SourcePoint.x;
309
310 DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
311 ((BltInfo->DestRect.bottom - 1) *
312 BltInfo->DestSurface->lDelta) + 2 *
313 BltInfo->DestRect.left;
314
315 for (j = BltInfo->DestRect.bottom - 1;
316 BltInfo->DestRect.top <= j; j--)
317 {
318 SourceBits = SourceLine;
319 DestBits = DestLine;
320 for (i = BltInfo->DestRect.left; i <
321 BltInfo->DestRect.right; i++)
322 {
323 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
324 BltInfo->XlateSourceToDest,
325 *((WORD *)SourceBits));
326 SourceBits += 2;
327 DestBits += 2;
328 }
329 SourceLine -= BltInfo->SourceSurface->lDelta;
330 DestLine -= BltInfo->DestSurface->lDelta;
331 }
332 }
333 }
334 break;
335
336 case BMF_24BPP:
337 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
338 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
339 3 * BltInfo->SourcePoint.x;
340
341 DestLine = DestBits;
342
343 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
344 {
345 SourceBits = SourceLine;
346 DestBits = DestLine;
347
348 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
349 {
350 xColor = (*(SourceBits + 2) << 0x10) +
351 (*(SourceBits + 1) << 0x08) + (*(SourceBits));
352
353 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
354 BltInfo->XlateSourceToDest, xColor);
355
356 SourceBits += 3;
357 DestBits += 2;
358 }
359 SourceLine += BltInfo->SourceSurface->lDelta;
360 DestLine += BltInfo->DestSurface->lDelta;
361 }
362 break;
363
364 case BMF_32BPP:
365 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
366 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
367 4 * BltInfo->SourcePoint.x;
368
369 DestLine = DestBits;
370
371 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
372 {
373 SourceBits = SourceLine;
374 DestBits = DestLine;
375
376 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
377 {
378 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
379 BltInfo->XlateSourceToDest,
380 *((PDWORD) SourceBits));
381 SourceBits += 4;
382 DestBits += 2;
383 }
384
385 SourceLine += BltInfo->SourceSurface->lDelta;
386 DestLine += BltInfo->DestSurface->lDelta;
387 }
388 break;
389
390 default:
391 DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n",
392 BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
393 return FALSE;
394 }
395
396 return TRUE;
397 }
398
399 /* Optimize for bitBlt */
400 BOOLEAN
401 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
402 {
403 LONG DestY;
404
405 #if defined(_M_IX86) && !defined(_MSC_VER)
406 /* This is about 10% faster than the generic C code below */
407 ULONG delta = DestSurface->lDelta;
408 ULONG width = (DestRect->right - DestRect->left) ;
409 PULONG pos = (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1));
410 color = (color&0xffff); /* If the color value is "abcd", put "abcdabcd" into color */
411 color += (color<<16);
412
413 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
414 {
415 __asm__ __volatile__ (
416 "cld\n\t"
417 "mov %1,%%ebx\n\t"
418 "mov %2,%%edi\n\t"
419 "test $0x03, %%edi\n\t" /* Align to fullword boundary */
420 "jz 1f\n\t"
421 "stosw\n\t"
422 "dec %%ebx\n\t"
423 "jz 2f\n"
424 "1:\n\t"
425 "mov %%ebx,%%ecx\n\t" /* Setup count of fullwords to fill */
426 "shr $1,%%ecx\n\t"
427 "rep stosl\n\t" /* The actual fill */
428 "test $0x01, %%ebx\n\t" /* One left to do at the right side? */
429 "jz 2f\n\t"
430 "stosw\n"
431 "2:"
432 :
433 : "a" (color), "r" (width), "m" (pos)
434 : "%ecx", "%ebx", "%edi");
435 pos =(PULONG)((ULONG_PTR)pos + delta);
436 }
437 #else /* _M_IX86 */
438
439 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
440 {
441 DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
442 }
443 #endif
444 return TRUE;
445 }
446
447 BOOLEAN
448 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
449 RECTL* DestRect, RECTL *SourceRect,
450 XLATEOBJ *ColorTranslation, ULONG iTransColor)
451 {
452 LONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, wd;
453 ULONG *DestBits, Source, Dest;
454
455 LONG DstHeight;
456 LONG DstWidth;
457 LONG SrcHeight;
458 LONG SrcWidth;
459
460 DstHeight = DestRect->bottom - DestRect->top;
461 DstWidth = DestRect->right - DestRect->left;
462 SrcHeight = SourceRect->bottom - SourceRect->top;
463 SrcWidth = SourceRect->right - SourceRect->left;
464
465 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
466 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
467 (DestRect->left << 1) +
468 DestRect->top * DestSurf->lDelta);
469 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
470
471 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
472 {
473 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
474 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
475 {
476 Dest = *DestBits;
477
478 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
479 if (SourceX >= 0 && SourceY >= 0 &&
480 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
481 {
482 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
483 if(Source != iTransColor)
484 {
485 Dest &= 0xFFFF0000;
486 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
487 }
488 }
489
490 SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth;
491 if (SourceX >= 0 && SourceY >= 0 &&
492 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
493 {
494 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
495 if(Source != iTransColor)
496 {
497 Dest &= 0xFFFF;
498 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
499 }
500 }
501
502 *DestBits = Dest;
503 }
504
505 if(X < DestRect->right)
506 {
507 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
508 if (SourceX >= 0 && SourceY >= 0 &&
509 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
510 {
511 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
512 if(Source != iTransColor)
513 {
514 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation,
515 Source);
516 }
517 }
518
519 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
520 }
521
522 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
523 }
524
525 return TRUE;
526 }
527
528 /* EOF */