Fixed some issues found by winapi_check.
[wine] / dlls / msvideo / drawdib.c
1 /*
2  * Copyright 2000 Bradley Baetz
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * FIXME: Some flags are ignored
19  *
20  * Handle palettes
21  */
22
23 #include <string.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "wine/winbase16.h"
29 #include "wine/debug.h"
30 #include "vfw.h"
31 #include "vfw16.h"
32 #include "windef.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
35
36 typedef struct {
37         HDC hdc;
38         INT dxDst;
39         INT dyDst;
40         LPBITMAPINFOHEADER lpbi;
41         INT dxSrc;
42         INT dySrc;
43         HPALETTE hpal;                          /* Palette to use for the DIB */
44         BOOL begun;                                     /* DrawDibBegin has been called */
45         LPBITMAPINFOHEADER lpbiOut;     /* Output format */
46         HIC hic;                                        /* HIC for decompression */
47         HDC hMemDC;                                     /* DC for buffering */
48         HBITMAP hOldDib;                        /* Original Dib */
49         HBITMAP hDib;                           /* DibSection */
50         LPVOID lpvbits;                         /* Buffer for holding decompressed dib */
51 } WINE_HDD;
52
53 int num_colours(LPBITMAPINFOHEADER lpbi)
54 {
55         if(lpbi->biClrUsed)
56                 return lpbi->biClrUsed;
57         if(lpbi->biBitCount<=8)
58                 return 1<<lpbi->biBitCount;
59         return 0;
60 }
61
62 /***********************************************************************
63  *              DrawDibOpen             [MSVFW32.@]
64  */
65 HDRAWDIB VFWAPI DrawDibOpen(void) {
66         HDRAWDIB hdd;
67
68         TRACE("(void)\n");
69         hdd = GlobalAlloc16(GHND,sizeof(WINE_HDD));
70         TRACE("=> %d\n",hdd);
71         return hdd;
72 }
73
74 /***********************************************************************
75  *              DrawDibOpen             [MSVIDEO.102]
76  */
77 HDRAWDIB16 VFWAPI DrawDibOpen16(void) {
78         return (HDRAWDIB16)DrawDibOpen();
79 }
80
81 /***********************************************************************
82  *              DrawDibClose            [MSVFW32.@]
83  */
84 BOOL VFWAPI DrawDibClose(HDRAWDIB hdd) {
85         WINE_HDD *whdd = GlobalLock16(hdd);
86
87         TRACE("(0x%08lx)\n",(DWORD)hdd);
88
89         if (!whdd)
90                 return FALSE;
91
92         if (whdd->begun)
93                 DrawDibEnd(hdd);
94
95         GlobalUnlock16(hdd);
96         GlobalFree16(hdd);
97         return TRUE;
98 }
99
100 /***********************************************************************
101  *              DrawDibClose            [MSVIDEO.103]
102  */
103 BOOL16 VFWAPI DrawDibClose16(HDRAWDIB16 hdd) {
104         return DrawDibClose(hdd);
105 }
106
107 /***********************************************************************
108  *              DrawDibEnd              [MSVFW32.@]
109  */
110 BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd) {
111         BOOL ret = TRUE;
112         WINE_HDD *whdd = GlobalLock16(hdd);
113
114         TRACE("(0x%08lx)\n",(DWORD)hdd);
115
116         whdd->hpal = 0; /* Do not free this */
117         whdd->hdc = 0;
118         if (whdd->lpbi) {
119                 HeapFree(GetProcessHeap(),0,whdd->lpbi);
120                 whdd->lpbi = NULL;
121         }
122         if (whdd->lpbiOut) {
123                 HeapFree(GetProcessHeap(),0,whdd->lpbiOut);
124                 whdd->lpbiOut = NULL;
125         }
126
127         whdd->begun = FALSE;
128
129         /*if (whdd->lpvbits)
130           HeapFree(GetProcessHeap(),0,whdd->lpvbuf);*/
131
132         if (whdd->hMemDC) {
133                 SelectObject(whdd->hMemDC,whdd->hOldDib);
134                 DeleteDC(whdd->hMemDC);
135         }
136
137         if (whdd->hDib)
138                 DeleteObject(whdd->hDib);
139
140         if (whdd->hic) {
141                 ICDecompressEnd(whdd->hic);
142                 ICClose(whdd->hic);
143         }
144
145         whdd->lpvbits = NULL;
146
147         GlobalUnlock16(hdd);
148         return ret;
149 }
150
151 /***********************************************************************
152  *              DrawDibEnd              [MSVIDEO.105]
153  */
154 BOOL16 VFWAPI DrawDibEnd16(HDRAWDIB16 hdd) {
155         return DrawDibEnd(hdd);
156 }
157
158 /***********************************************************************
159  *              DrawDibBegin            [MSVFW32.@]
160  */
161 BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
162                                                  HDC      hdc,
163                                                  INT      dxDst,
164                                                  INT      dyDst,
165                                                  LPBITMAPINFOHEADER lpbi,
166                                                  INT      dxSrc,
167                                                  INT      dySrc,
168                                                  UINT     wFlags) {
169         BOOL ret = TRUE;
170         WINE_HDD *whdd;
171
172         TRACE("(%d,0x%lx,%d,%d,%p,%d,%d,0x%08lx)\n",
173                 hdd,(DWORD)hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,(DWORD)wFlags
174         );
175         TRACE("lpbi: %ld,%ld/%ld,%d,%d,%ld,%ld,%ld,%ld,%ld,%ld\n",
176                   lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes,
177                   lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage,
178                   lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed,
179                   lpbi->biClrImportant);
180
181         if (wFlags & ~(DDF_BUFFER))
182                 FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER));
183
184         whdd = (WINE_HDD*)GlobalLock16(hdd);
185         if (!whdd) return FALSE;
186
187         if (whdd->begun)
188                 DrawDibEnd(hdd);
189
190         if (lpbi->biCompression) {
191                 DWORD size = 0;
192
193                 whdd->hic = ICOpen(ICTYPE_VIDEO,lpbi->biCompression,ICMODE_DECOMPRESS);
194                 if (!whdd->hic) {
195                         WARN("Could not open IC. biCompression == 0x%08lx\n",lpbi->biCompression);
196                         ret = FALSE;
197                 }
198
199                 if (ret) {
200                         size = ICDecompressGetFormat(whdd->hic,lpbi,NULL);
201                         if (size == ICERR_UNSUPPORTED) {
202                                 WARN("Codec doesn't support GetFormat, giving up.\n");
203                                 ret = FALSE;
204                         }
205                 }
206
207                 if (ret) {
208                         whdd->lpbiOut = HeapAlloc(GetProcessHeap(),0,size);
209
210                         if (ICDecompressGetFormat(whdd->hic,lpbi,whdd->lpbiOut) != ICERR_OK)
211                                 ret = FALSE;
212                 }
213
214                 if (ret) {
215                         /* FIXME: Use Ex functions if available? */
216                         if (ICDecompressBegin(whdd->hic,lpbi,whdd->lpbiOut) != ICERR_OK)
217                                 ret = FALSE;
218
219                         TRACE("biSizeImage == %ld\n",whdd->lpbiOut->biSizeImage);
220                         TRACE("biCompression == %ld\n",whdd->lpbiOut->biCompression);
221                         TRACE("biBitCount == %d\n",whdd->lpbiOut->biBitCount);
222                 }
223         } else {
224                 DWORD dwSize;
225                 /* No compression */
226                 TRACE("Not compressed!\n");
227                 dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD);
228                 whdd->lpbiOut = HeapAlloc(GetProcessHeap(),0,dwSize);
229                 memcpy(whdd->lpbiOut,lpbi,dwSize);
230         }
231
232         if (ret) {
233                 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(),0,whdd->lpbiOut->biSizeImage);*/
234
235                 whdd->hMemDC = CreateCompatibleDC(hdc);
236                 TRACE("Creating: %ld,%p\n",whdd->lpbiOut->biSize,whdd->lpvbits);
237                 whdd->hDib = CreateDIBSection(whdd->hMemDC,(BITMAPINFO *)whdd->lpbiOut,DIB_RGB_COLORS,&(whdd->lpvbits),0,0);
238                 if (!whdd->hDib) {
239                         TRACE("Error: %ld\n",GetLastError());
240                 }
241                 TRACE("Created: %d,%p\n",whdd->hDib,whdd->lpvbits);
242                 whdd->hOldDib = SelectObject(whdd->hMemDC,whdd->hDib);
243         }
244
245         if (ret) {
246                 whdd->hdc = hdc;
247                 whdd->dxDst = dxDst;
248                 whdd->dyDst = dyDst;
249                 whdd->lpbi = HeapAlloc(GetProcessHeap(),0,lpbi->biSize);
250                 memcpy(whdd->lpbi,lpbi,lpbi->biSize);
251                 whdd->dxSrc = dxSrc;
252                 whdd->dySrc = dySrc;
253                 whdd->begun = TRUE;
254                 whdd->hpal = 0;
255         } else {
256                 if (whdd->hic)
257                         ICClose(whdd->hic);
258                 if (whdd->lpbiOut) {
259                         HeapFree(GetProcessHeap(),0,whdd->lpbiOut);
260                         whdd->lpbiOut = NULL;
261                 }
262         }
263
264         GlobalUnlock16(hdd);
265
266         return ret;
267 }
268
269 /************************************************************************
270  *              DrawDibBegin            [MSVIDEO.104]
271  */
272 BOOL16 VFWAPI DrawDibBegin16(HDRAWDIB16 hdd,
273                                                    HDC16      hdc,
274                                                    INT16      dxDst,
275                                                    INT16      dyDst,
276                                                    LPBITMAPINFOHEADER lpbi,
277                                                    INT16      dxSrc,
278                                                    INT16      dySrc,
279                                                    UINT16     wFlags) {
280         return DrawDibBegin(hdd,hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,wFlags);
281 }
282
283 /**********************************************************************
284  *              DrawDibDraw             [MSVFW32.@]
285  */
286 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
287         INT xDst, INT yDst, INT dxDst, INT dyDst,
288         LPBITMAPINFOHEADER lpbi,
289         LPVOID lpBits,
290         INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
291         UINT wFlags
292 ) {
293         WINE_HDD *whdd;
294         BOOL ret = TRUE;
295
296         TRACE("(%d,0x%lx,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08lx)\n",
297                   hdd,(DWORD)hdc,xDst,yDst,dxDst,dyDst,lpbi,lpBits,xSrc,ySrc,dxSrc,dySrc,(DWORD)wFlags
298         );
299
300         if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME |
301                                    DDF_UPDATE | DDF_DONTDRAW))
302                 FIXME("wFlags == 0x%08lx not handled\n",(DWORD)wFlags);
303
304         if (!lpBits) {
305                 /* Undocumented? */
306                 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD));
307         }
308
309         whdd = GlobalLock16(hdd);
310
311 #define CHANGED(x) (whdd->x != x)
312
313         if ((!whdd->begun) || (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) || (!(wFlags & DDF_SAME_DRAW) &&
314                  (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst)))) {
315                 TRACE("Something changed!\n");
316                 ret = DrawDibBegin(hdd,hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,0);
317         }
318
319 #undef CHANGED
320
321         if ((dxDst == -1) && (dyDst == -1)) {
322                 dxDst = dxSrc;
323                 dyDst = dySrc;
324         }
325
326         if (!(wFlags & DDF_UPDATE)) {
327             /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
328             if ((lpbi->biCompression == BI_RGB) && (lpbi->biSizeImage == 0))
329                     lpbi->biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
330
331                 if (lpbi->biCompression) {
332                     DWORD flags = 0;
333
334                         TRACE("Compression == 0x%08lx\n",lpbi->biCompression);
335
336                         if (wFlags & DDF_NOTKEYFRAME)
337                             flags |= ICDECOMPRESS_NOTKEYFRAME;
338
339                         ICDecompress(whdd->hic,flags,lpbi,lpBits,whdd->lpbiOut,whdd->lpvbits);
340                 } else {
341                     memcpy(whdd->lpvbits,lpBits,lpbi->biSizeImage);
342                 }
343         }
344         if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
345             SelectPalette(hdc,whdd->hpal,FALSE);
346
347         if (!(StretchBlt(whdd->hdc,xDst,yDst,dxDst,dyDst,whdd->hMemDC,xSrc,ySrc,dxSrc,dySrc,SRCCOPY)))
348             ret = FALSE;
349
350         GlobalUnlock16(hdd);
351         return ret;
352 }
353
354 /**********************************************************************
355  *              DrawDibDraw             [MSVIDEO.106]
356  */
357 BOOL16 VFWAPI DrawDibDraw16(HDRAWDIB16 hdd,
358                                                   HDC16 hdc,
359                                                   INT16 xDst,
360                                                   INT16 yDst,
361                                                   INT16 dxDst,
362                                                   INT16 dyDst,
363                                                   LPBITMAPINFOHEADER lpbi,
364                                                   LPVOID lpBits,
365                                                   INT16 xSrc,
366                                                   INT16 ySrc,
367                                                   INT16 dxSrc,
368                                                   INT16 dySrc,
369                                                   UINT16 wFlags) {
370         return DrawDibDraw(hdd,hdc,xDst,yDst,dxDst,dyDst,lpbi,lpBits,xSrc,ySrc,dxSrc,dySrc,wFlags);
371 }
372
373 /*************************************************************************
374  *              DrawDibStart            [MSVFW32.@]
375  */
376 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
377         FIXME("(0x%08lx,%ld), stub\n",(DWORD)hdd,rate);
378         return TRUE;
379 }
380
381 /*************************************************************************
382  *              DrawDibStart            [MSVIDEO.118]
383  */
384 BOOL16 VFWAPI DrawDibStart16(HDRAWDIB16 hdd, DWORD rate) {
385         return DrawDibStart(hdd,rate);
386 }
387
388 /*************************************************************************
389  *              DrawDibStop             [MSVFW32.@]
390  */
391 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
392         FIXME("(0x%08lx), stub\n",(DWORD)hdd);
393         return TRUE;
394 }
395
396 /*************************************************************************
397  *              DrawDibStop             [MSVIDEO.119]
398  */
399 BOOL16 DrawDibStop16(HDRAWDIB16 hdd) {
400         return DrawDibStop(hdd);
401 }
402
403 /***********************************************************************
404  *              DrawDibSetPalette       [MSVFW32.@]
405  */
406 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal) {
407         WINE_HDD *whdd;
408
409         TRACE("(0x%08lx,0x%08lx)\n",(DWORD)hdd,(DWORD)hpal);
410
411         whdd = GlobalLock16(hdd);
412         whdd->hpal = hpal;
413
414         if (whdd->begun) {
415                 SelectPalette(whdd->hdc,hpal,0);
416                 RealizePalette(whdd->hdc);
417         }
418         GlobalUnlock16(hdd);
419         return TRUE;
420 }
421
422 /***********************************************************************
423  *              DrawDibSetPalette       [MSVIDEO.110]
424  */
425 BOOL16 VFWAPI DrawDibSetPalette16(HDRAWDIB16 hdd, HPALETTE16 hpal) {
426         return DrawDibSetPalette(hdd,hpal);
427 }
428
429 /***********************************************************************
430  *              DrawDibGetPalette       [MSVFW32.@]
431  */
432 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd) {
433         WINE_HDD *whdd;
434         HPALETTE ret;
435
436         TRACE("(0x%08lx)\n",(DWORD)hdd);
437
438         whdd = GlobalLock16(hdd);
439         ret = whdd->hpal;
440         GlobalUnlock16(hdd);
441         return ret;
442 }
443
444 /***********************************************************************
445  *              DrawDibGetPalette       [MSVIDEO.108]
446  */
447 HPALETTE16 VFWAPI DrawDibGetPalette16(HDRAWDIB16 hdd) {
448         return (HPALETTE16)DrawDibGetPalette(hdd);
449 }
450
451 /***********************************************************************
452  *              DrawDibRealize          [MSVFW32.@]
453  */
454 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground) {
455         WINE_HDD *whdd;
456         HPALETTE oldPal;
457         UINT ret = 0;
458
459         FIXME("(%d,0x%08lx,%d), stub\n",hdd,(DWORD)hdc,fBackground);
460
461         whdd = GlobalLock16(hdd);
462
463         if (!whdd || !(whdd->begun)) {
464                 ret = 0;
465                 goto out;
466         }
467
468         if (!whdd->hpal)
469                 whdd->hpal = CreateHalftonePalette(hdc);
470
471         oldPal = SelectPalette(hdc,whdd->hpal,fBackground);
472         ret = RealizePalette(hdc);
473
474  out:
475         GlobalUnlock16(hdd);
476
477         TRACE("=> %u\n",ret);
478         return ret;
479 }
480
481 /***********************************************************************
482  *              DrawDibRealize          [MSVIDEO.112]
483  */
484 UINT16 VFWAPI DrawDibRealize16(HDRAWDIB16 hdd, HDC16 hdc, BOOL16 fBackground) {
485         return (UINT16)DrawDibRealize(hdd,hdc,fBackground);
486 }