source: trunk/src/gdi32/blit.cpp@ 7327

Last change on this file since 7327 was 7327, checked in by sandervl, 24 years ago

workaround added for 32 bpp blitting with matrox display driver

File size: 27.1 KB
Line 
1/* $Id: blit.cpp,v 1.35 2001-11-13 13:18:22 sandervl Exp $ */
2
3/*
4 * GDI32 blit code
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Patrick Haller
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#include <os2win.h>
13#include <stdlib.h>
14#include <stdarg.h>
15#include <string.h>
16#include <cpuhlp.h>
17#include "misc.h"
18#include "dibsect.h"
19#include "rgbcvt.h"
20
21#define DBG_LOCALLOG DBG_blit
22#include "dbglocal.h"
23
24static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr);
25ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy);
26
27//******************************************************************************
28//******************************************************************************
29BOOL WIN32API StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest,
30 int nWidthDest, int nHeightDest,
31 HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
32 int nWidthSrc, int nHeightSrc, DWORD dwRop)
33{
34 BOOL rc;
35
36 dprintf(("GDI32: StretchBlt Dest: %x (%d, %d) size (%d, %d) ROP %x",
37 hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop));
38 dprintf(("GDI32: StretchBlt Src : %x (%d, %d) size (%d, %d)\n",
39 hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc));
40 SetLastError(ERROR_SUCCESS);
41 if(DIBSection::getSection() != NULL)
42 {
43 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
44 if(dsect)
45 {
46 rc = dsect->BitBlt( hdcDest,
47 nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
48 nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
49 dwRop);
50 return rc;
51 }
52 }
53 return O32_StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, dwRop);
54}
55//******************************************************************************
56//******************************************************************************
57BOOL WIN32API BitBlt(HDC hdcDest,
58 int nXDest,
59 int nYDest,
60 int nWidth,
61 int nHeight,
62 HDC hdcSrc,
63 int nXSrc,
64 int nYSrc,
65 DWORD dwRop)
66{
67 BOOL rc;
68
69 SetLastError(ERROR_SUCCESS);
70 if(DIBSection::getSection() != NULL)
71 {
72 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
73 if(dsect)
74 {
75 return dsect->BitBlt(hdcDest,
76 nXDest,
77 nYDest,
78 nWidth,
79 nHeight,
80 nXSrc,
81 nYSrc,
82 nWidth,
83 nHeight,
84 dwRop);
85 }
86 }
87 dprintf(("GDI32: BitBlt to hdc %X from hdc %x (%d,%d) to (%d,%d), (%d,%d) rop %X\n",
88 hdcDest, hdcSrc, nXSrc, nYSrc, nXDest, nYDest, nWidth, nHeight, dwRop));
89 return O32_BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop);
90}
91//******************************************************************************
92//******************************************************************************
93static INT SetDIBitsToDevice_(HDC hdc, INT xDest, INT yDest, DWORD cx,
94 DWORD cy, INT xSrc, INT ySrc,
95 UINT startscan, UINT lines, LPCVOID bits,
96 const BITMAPINFO *info, UINT coloruse)
97{
98 INT result, imgsize, palsize, height, width;
99 char *ptr;
100 ULONG compression = 0, bmpsize;
101 WORD *newbits = NULL;
102 DWORD bitfields[3];
103
104 dprintf(("GDI32: SetDIBitsToDevice hdc:%X xDest:%d yDest:%d, cx:%d, cy:%d, xSrc:%d, ySrc:%d, startscan:%d, lines:%d \nGDI32: bits 0x%X, info 0x%X, coloruse %d",
105 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse));
106
107 SetLastError(ERROR_SUCCESS);
108 if(info == NULL) {
109 goto invalid_parameter;
110 }
111 height = info->bmiHeader.biHeight;
112 width = info->bmiHeader.biWidth;
113
114 if (height < 0) height = -height;
115 if (!lines || (startscan >= height)) {
116 goto invalid_parameter;
117 }
118 if (startscan + lines > height) lines = height - startscan;
119
120 if (ySrc < startscan) ySrc = startscan;
121 else if (ySrc >= startscan + lines) goto invalid_parameter;
122
123 if (xSrc >= width) goto invalid_parameter;
124
125 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
126
127 if (xSrc + cx >= width) cx = width - xSrc;
128
129 if (!cx || !cy) goto invalid_parameter;
130
131 //SvL: RP7's bitmap size is not correct; fix it here or else
132 // the blit is messed up in Open32
133 imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
134 info->bmiHeader.biWidth, info->bmiHeader.biHeight);
135 bmpsize = info->bmiHeader.biSizeImage;
136 if(info->bmiHeader.biCompression == 0 && info->bmiHeader.biSizeImage &&
137 info->bmiHeader.biSizeImage < imgsize)
138 {
139 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = imgsize;
140 }
141
142 switch(info->bmiHeader.biBitCount) {
143 case 15:
144 case 16: //Default if BI_BITFIELDS not set is RGB 555
145 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
146 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
147 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
148 break;
149
150 case 24:
151 case 32:
152 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
153 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
154 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
155 break;
156 default:
157 bitfields[0] = 0;
158 bitfields[1] = 0;
159 bitfields[2] = 0;
160 break;
161 }
162
163 if(bitfields[1] == 0x3E0)
164 {//RGB 555?
165 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
166
167 newbits = (WORD *)malloc(imgsize);
168 if(CPUFeatures & CPUID_MMX) {
169 RGB555to565MMX(newbits, (WORD *)bits, imgsize/sizeof(WORD));
170 }
171 else RGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
172 bits = newbits;
173 }
174
175 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
176 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
177 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
178 compression = BI_BITFIELDS;
179
180 }
181 if(startscan != 0 || lines != info->bmiHeader.biHeight) {
182 dprintf(("WARNING: SetDIBitsToDevice startscan != 0 || lines != info->bmiHeader.biHeight"));
183 }
184
185 result = O32_StretchDIBits(hdc, xDest, yDest, cx, cy, xSrc, ySrc,
186 cx, cy, (void *)bits,
187 (PBITMAPINFO)info, coloruse, SRCCOPY);
188
189 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
190 if(result != info->bmiHeader.biHeight) {
191 dprintf(("SetDIBitsToDevice failed with rc %x", result));
192 }
193 else
194 {
195 result = info->bmiHeader.biHeight;
196
197 DIBSection *destdib = DIBSection::findHDC(hdc);
198 if(destdib) {
199 if(cx == info->bmiHeader.biWidth && cy == info->bmiHeader.biHeight &&
200 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
201 destdib->GetBitCount() == 8)
202 {
203 destdib->sync(xDest, yDest, cx, cy, (PVOID)bits);
204 }
205 else destdib->sync(hdc, yDest, cy);
206 }
207 }
208 dprintf(("GDI32: SetDIBitsToDevice hdc:%X xDest:%d yDest:%d, cx:%d, cy:%d, xSrc:%d, ySrc:%d, startscan:%d, lines:%d \nGDI32: bits 0x%X, info 0x%X, coloruse %d returned %d",
209 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse, result));
210 dprintf(("GDI32: SetDIBitsToDevice %d %d %d %d %x %d", info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biPlanes, info->bmiHeader.biBitCount, info->bmiHeader.biCompression, info->bmiHeader.biSizeImage));
211
212 if(compression == BI_BITFIELDS) {
213 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
214 }
215 if(newbits) free(newbits);
216 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = bmpsize;
217 return result;
218
219invalid_parameter:
220 SetLastError(ERROR_INVALID_PARAMETER);
221 return 0;
222}
223//******************************************************************************
224//******************************************************************************
225INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
226 DWORD cy, INT xSrc, INT ySrc,
227 UINT startscan, UINT lines, LPCVOID bits,
228 const BITMAPINFO *info, UINT coloruse)
229{
230 static BOOL fMatrox32BppBug = FALSE;
231 INT rc = 0;
232 char *newBits = NULL;
233
234 //If upside down, reverse scanlines and call SetDIBitsToDevice again
235 if(info->bmiHeader.biHeight < 0 && info->bmiHeader.biBitCount != 8 && info->bmiHeader.biCompression == 0) {
236 // upside down
237 INT rc = -1;
238 BITMAPINFO newInfo;
239 newInfo.bmiHeader = info->bmiHeader;
240 long lLineByte = ((newInfo.bmiHeader.biWidth * (info->bmiHeader.biBitCount == 15 ? 16 : info->bmiHeader.biBitCount) + 31) / 32) * 4;
241 long lHeight = -newInfo.bmiHeader.biHeight;
242 newInfo.bmiHeader.biHeight = -info->bmiHeader.biHeight;
243
244 char *newBits = (char *)malloc( lLineByte * lHeight );
245 if(newBits) {
246 unsigned char *pbSrc = (unsigned char *)bits + lLineByte * (lHeight - 1);
247 unsigned char *pbDst = (unsigned char *)newBits;
248 for(int y = 0; y < lHeight; y++) {
249 memcpy( pbDst, pbSrc, lLineByte );
250 pbDst += lLineByte;
251 pbSrc -= lLineByte;
252 }
253 rc = SetDIBitsToDevice( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (void *)newBits, &newInfo, coloruse );
254 free( newBits );
255 }
256 else DebugInt3();
257
258 return rc;
259 }
260
261 //We must convert 32 bpp bitmap data to 24 bpp on systems with the Matrox
262 //display driver. (GpiDrawBits for 32 bpp fails with insufficient memory error)
263 if(info->bmiHeader.biBitCount == 32 && fMatrox32BppBug)
264 {
265 BITMAPINFO newInfo;
266 newInfo.bmiHeader = info->bmiHeader;
267
268 long lLineWidth;
269 long lHeight = (newInfo.bmiHeader.biHeight > 0) ? newInfo.bmiHeader.biHeight : -newInfo.bmiHeader.biHeight;
270 long lWidth = newInfo.bmiHeader.biWidth;
271
272 newInfo.bmiHeader.biBitCount = 24;
273 newInfo.bmiHeader.biSizeImage = CalcBitmapSize(24, newInfo.bmiHeader.biWidth,
274 newInfo.bmiHeader.biHeight);
275
276 lLineWidth = newInfo.bmiHeader.biSizeImage / lHeight;
277
278 //convert 32 bits bitmap data to 24 bits
279 newBits = (char *)malloc(newInfo.bmiHeader.biSizeImage+16); //extra room needed for copying (too much)
280 if(!newBits) {
281 DebugInt3();
282 return -1;
283 }
284 unsigned char *pbSrc = (unsigned char *)bits;
285 unsigned char *pbDst = (unsigned char *)newBits;
286 //not very efficient
287 for(int i = 0; i < lHeight; i++) {
288 for(int j=0;j<lWidth;j++) {
289 *(DWORD *)pbDst = *(DWORD *)pbSrc;
290 pbSrc += 4;
291 pbDst += 3;
292 }
293 //24 bpp scanline must be aligned at 4 byte boundary
294 pbDst += (lLineWidth - 3*lWidth);
295 }
296 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, newBits, &newInfo, coloruse );
297 free(newBits);
298 return rc;
299 }
300 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse );
301
302 if(rc == -1 && info->bmiHeader.biBitCount == 32 && !fMatrox32BppBug)
303 {
304 //The Matrox driver seems to have some difficulty blitting 32bpp
305 //data. (out of memory error) The same operation works fine with SDD.
306 fMatrox32BppBug = TRUE;
307 return SetDIBitsToDevice(hdc, xDest, yDest, cx,
308 cy, xSrc, ySrc,
309 startscan, lines, bits,
310 info, coloruse);
311 }
312 return rc;
313
314//SvL: Breaks startup bitmap of Acrobat Reader 4.05
315#if 0
316 else
317 if(info->bmiHeader.biBitCount == 8 && info->bmiHeader.biCompression == 0 && !(GetDeviceCaps( hdc, RASTERCAPS ) & RC_PALETTE)) {
318 INT rc = 0;
319 // convert 8bit to 24bit
320
321 BITMAPINFO newInfo;
322 newInfo.bmiHeader = info->bmiHeader;
323 newInfo.bmiHeader.biBitCount = 24;
324 long lLineByte24 = ((newInfo.bmiHeader.biWidth * 24 + 31) / 32) * 4;
325 long lLineByte8 = ((newInfo.bmiHeader.biWidth * 8 + 31) / 32) * 4;
326 long lHeight = newInfo.bmiHeader.biHeight;
327 if(lHeight < 0) lHeight = -lHeight;
328
329 char *newBits = (char *)malloc( lLineByte24 * lHeight );
330 if(newBits) {
331 //
332 // Get Palette Entries
333 //
334 PALETTEENTRY aEntries[256];
335 LOGPALETTE *pLog = (LOGPALETTE *)malloc( sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256 );
336 pLog->palVersion = 0x300;
337 pLog->palNumEntries = 256;
338
339 HPALETTE hPaletteDummy = CreatePalette( pLog );
340 free( pLog );
341 HPALETTE hPalette = SelectPalette( hdc, hPaletteDummy, FALSE );
342 GetPaletteEntries( hPalette, 0, 255, aEntries );
343 SelectPalette( hdc, hPalette, FALSE );
344 DeleteObject( hPaletteDummy );
345
346 //
347 // convert 8bit to 24bit
348 //
349 if(newInfo.bmiHeader.biHeight > 0) {
350 unsigned char *pbSrc = (unsigned char *)bits;
351 unsigned char *pbDst = (unsigned char *)newBits;
352 for(int y = 0; y < lHeight; y++) {
353 for(int x = 0; x < newInfo.bmiHeader.biWidth; x++) {
354 PALETTEENTRY src = aEntries[pbSrc[x]];
355 pbDst[x * 3 + 0] = src.peBlue;
356 pbDst[x * 3 + 1] = src.peGreen;
357 pbDst[x * 3 + 2] = src.peRed;
358 }
359 pbDst += lLineByte24;
360 pbSrc += lLineByte8;
361 }
362 } else {
363 // upside down
364 newInfo.bmiHeader.biHeight = -info->bmiHeader.biHeight;
365 unsigned char *pbSrc = (unsigned char *)bits + lLineByte8 * (lHeight - 1);
366 unsigned char *pbDst = (unsigned char *)newBits;
367 for(int y = 0; y < lHeight; y++) {
368 for(int x = 0; x < newInfo.bmiHeader.biWidth; x++) {
369 PALETTEENTRY src = aEntries[pbSrc[x]];
370 pbDst[x * 3 + 0] = src.peBlue;
371 pbDst[x * 3 + 1] = src.peGreen;
372 pbDst[x * 3 + 2] = src.peRed;
373 }
374 pbDst += lLineByte24;
375 pbSrc -= lLineByte8;
376 }
377 }
378 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (void *)newBits, &newInfo, DIB_RGB_COLORS );
379 free( newBits );
380 }
381 return rc;
382 }
383#endif
384}
385//******************************************************************************
386//******************************************************************************
387BOOL WIN32API PatBlt(HDC hdc,int nXLeft,int nYLeft,int nWidth,int nHeight,DWORD dwRop)
388{
389 BOOL rc;
390
391 dprintf(("PatBlt %x (%d,%d)(%d,%d) %x", hdc, nXLeft,nYLeft,nWidth,nHeight, dwRop));
392 //CB: Open32 bug: negative width/height not supported!
393 if (nWidth < 0)
394 {
395 nXLeft += nWidth+1;
396 nWidth = -nWidth;
397 }
398 if (nHeight < 0)
399 {
400 nYLeft += nHeight+1;
401 nHeight = -nHeight;
402 }
403 rc = O32_PatBlt(hdc,nXLeft,nYLeft,nWidth,nHeight,dwRop);
404 if(rc) {
405 DIBSection *destdib = DIBSection::findHDC(hdc);
406 if(destdib) {
407 destdib->sync(hdc, nYLeft, nHeight);
408 }
409 }
410
411 dprintf(("GDI32: PatBlt hdc %x (%d,%d) (%d,%d) returned %d\n",hdc, nXLeft,nYLeft,nWidth,nHeight,rc));
412 return(rc);
413}
414//******************************************************************************
415//******************************************************************************
416BOOL WIN32API MaskBlt( HDC arg1, int arg2, int arg3, int arg4, int arg5, HDC arg6, int arg7, int arg8, HBITMAP arg9, int arg10, int arg11, DWORD arg12)
417{
418 dprintf(("GDI32: MaskBlt"));
419 return O32_MaskBlt(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
420}
421//******************************************************************************
422//******************************************************************************
423BOOL WIN32API PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc,
424 int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask,
425 int xMast, int yMask)
426{
427 dprintf(("GDI32: PlgBlt, not implemented\n"));
428 return(FALSE);
429}
430//******************************************************************************
431//******************************************************************************
432static INT StretchDIBits_(HDC hdc, INT xDst, INT yDst, INT widthDst,
433 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
434 INT heightSrc, const void *bits,
435 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
436{
437 INT rc;
438 DWORD bitfields[3], compression = 0;
439 WORD *newbits = NULL;
440
441 dprintf(("GDI32: StretchDIBits %x to (%d,%d) (%d,%d) from (%d,%d) (%d,%d), %x %x %x %x", hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop));
442
443 if(info->bmiHeader.biBitCount == 1) {
444 dprintf(("WARNING: StretchDIBits does NOT work correctly for 1 bpp bitmaps!!"));
445 }
446
447 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
448 {
449 // workaround for open32 bug.
450 // If syscolors > 256 and wUsage == DIB_PAL_COLORS.
451
452 int i;
453 USHORT *pColorIndex = (USHORT *)info->bmiColors;
454 RGBQUAD *pColors = (RGBQUAD *) alloca(info->bmiHeader.biClrUsed *
455 sizeof(RGBQUAD));
456 BITMAPINFO *infoLoc = (BITMAPINFO *) alloca(sizeof(BITMAPINFO) +
457 info->bmiHeader.biClrUsed * sizeof(RGBQUAD));
458
459 memcpy(infoLoc, info, sizeof(BITMAPINFO));
460
461 if(GetDIBColorTable(hdc, 0, info->bmiHeader.biClrUsed, pColors) == 0) {
462 dprintf(("ERROR: StretchDIBits: GetDIBColorTable failed!!"));
463 return FALSE;
464 }
465 for(i=0;i<info->bmiHeader.biClrUsed;i++, pColorIndex++)
466 {
467 infoLoc->bmiColors[i] = pColors[*pColorIndex];
468 }
469
470 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
471 widthSrc, heightSrc, (void *)bits,
472 (PBITMAPINFO)infoLoc, DIB_RGB_COLORS, dwRop);
473
474 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
475 if(rc != heightSrc && rc != infoLoc->bmiHeader.biHeight) {
476 dprintf(("StretchDIBits failed with rc %x", rc));
477 }
478 else {
479 rc = heightSrc;
480
481 DIBSection *destdib = DIBSection::findHDC(hdc);
482 if(destdib) {
483 if(widthDst == widthSrc && heightDst == heightSrc &&
484 destdib->GetBitCount() == infoLoc->bmiHeader.biBitCount &&
485 destdib->GetBitCount() == 8)
486 {
487 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
488 }
489 else destdib->sync(hdc, yDst, heightDst);
490 }
491 }
492
493 return rc;
494 }
495
496 switch(info->bmiHeader.biBitCount) {
497 case 15:
498 case 16: //Default if BI_BITFIELDS not set is RGB 555
499 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
500 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
501 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
502 break;
503 case 24:
504 case 32:
505 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
506 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0xff00;
507 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0xff;
508 break;
509 default:
510 bitfields[0] = 0;
511 bitfields[1] = 0;
512 bitfields[2] = 0;
513 break;
514 }
515 if(bitfields[1] == 0x3E0)
516 {//RGB 555?
517 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
518
519 int imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
520 info->bmiHeader.biWidth, info->bmiHeader.biHeight);
521
522 newbits = (WORD *)malloc(imgsize);
523 if(CPUFeatures & CPUID_MMX) {
524 RGB555to565MMX(newbits, (WORD *)bits, imgsize/sizeof(WORD));
525 }
526 else RGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
527 bits = newbits;
528 }
529 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
530 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
531 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
532 compression = BI_BITFIELDS;
533 }
534
535 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
536 widthSrc, heightSrc, (void *)bits,
537 (PBITMAPINFO)info, wUsage, dwRop);
538
539 if(compression == BI_BITFIELDS) {
540 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
541 }
542 if(newbits) free(newbits);
543
544 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
545 if(rc != heightSrc && rc != info->bmiHeader.biHeight) {
546 dprintf(("StretchDIBits failed with rc %x", rc));
547 }
548 else
549 {
550 rc = heightSrc;
551
552 DIBSection *destdib = DIBSection::findHDC(hdc);
553 if(destdib) {
554 if(widthDst == widthSrc && heightDst == heightSrc &&
555 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
556 destdib->GetBitCount() == 8)
557 {
558 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
559 }
560 else destdib->sync(hdc, yDst, heightDst);
561 }
562 }
563
564 return rc;
565}
566//******************************************************************************
567//******************************************************************************
568INT WIN32API StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
569 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
570 INT heightSrc, const void *bits,
571 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
572{
573
574 if(info->bmiHeader.biHeight < 0) {
575 // upside down
576 INT rc = 0;
577 BITMAPINFO newInfo;
578 newInfo.bmiHeader = info->bmiHeader;
579 long lLineByte = ((newInfo.bmiHeader.biWidth * (info->bmiHeader.biBitCount == 15 ? 16 : info->bmiHeader.biBitCount) + 31) / 32) * 4;
580 long lHeight = -newInfo.bmiHeader.biHeight;
581 newInfo.bmiHeader.biHeight = -newInfo.bmiHeader.biHeight;
582
583 //TODO: doesn't work if memory is readonly!!
584 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
585
586 char *newBits = (char *)malloc( lLineByte * lHeight );
587 if(newBits) {
588 unsigned char *pbSrc = (unsigned char *)bits + lLineByte * (lHeight - 1);
589 unsigned char *pbDst = (unsigned char *)newBits;
590 for(int y = 0; y < lHeight; y++) {
591 memcpy( pbDst, pbSrc, lLineByte );
592 pbDst += lLineByte;
593 pbSrc -= lLineByte;
594 }
595 rc = StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, newBits, info, wUsage, dwRop);
596 free( newBits );
597 }
598
599 //TODO: doesn't work if memory is readonly!!
600 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
601 return rc;
602 } else {
603 return StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop);
604 }
605}
606//******************************************************************************
607//******************************************************************************
608int WIN32API SetStretchBltMode( HDC arg1, int arg2)
609{
610 dprintf(("GDI32: SetStretchBltMode 0x%08X, 0x%08X\n",arg1, arg2));
611
612 if(DIBSection::getSection() != NULL)
613 {
614 DIBSection *dsect = DIBSection::findHDC(arg1);
615 if(dsect)
616 {
617 dprintf((" - DC is DIBSection\n"));
618 }
619 }
620 return O32_SetStretchBltMode(arg1, arg2);
621}
622//******************************************************************************
623//******************************************************************************
624int WIN32API GetStretchBltMode( HDC arg1)
625{
626 dprintf(("GDI32: GetStretchBltMode"));
627 return O32_GetStretchBltMode(arg1);
628}
629//******************************************************************************
630//******************************************************************************
631static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr)
632{
633 ULONG cbPalette;
634
635 switch (pBHdr->biBitCount)
636 {
637 case 1:
638 case 4:
639 case 8:
640 cbPalette = (1 << pBHdr->biBitCount) * sizeof(RGBQUAD);
641 break;
642
643 case 16:
644 case 24:
645 case 32:
646 cbPalette = 0;
647 break;
648
649 default:
650 dprintf(("QueryPaletteSize: error pBHdr->biBitCount = %d", pBHdr->biBitCount));
651 cbPalette = -1;
652 }
653
654 return cbPalette;
655}
656//******************************************************************************
657//******************************************************************************
658ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
659{
660 ULONG alignment;
661 ULONG factor;
662 BOOL flag = TRUE; //true: '*' false: '/'
663
664 cy = cy < 0 ? -cy : cy;
665
666 switch(cBits)
667 {
668 case 1:
669 factor = 8;
670 flag = FALSE;
671 break;
672
673 case 4:
674 factor = 2;
675 flag = FALSE;
676 break;
677
678 case 8:
679 factor = 1;
680 break;
681
682 case 16:
683 factor = 2;
684 break;
685
686 case 24:
687 factor = 3;
688 break;
689
690 case 32:
691 return cx*cy*4;
692
693 default:
694 return 0;
695 }
696
697 if (flag)
698 alignment = (cx = (cx*factor)) % 4;
699 else
700 alignment = (cx = ((cx+factor-1)/factor)) % 4;
701
702 if (alignment != 0)
703 cx += 4 - alignment;
704
705 return cx*cy;
706}
707//******************************************************************************
708//******************************************************************************
Note: See TracBrowser for help on using the repository browser.