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

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

use critical section in dib section class instead of vmutex

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