Large-scale renaming of all Win32 functions and types to use the
[wine] / graphics / x11drv / bitmap.c
1 /*
2  * X11DRV bitmap objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #ifndef X_DISPLAY_MISSING
10
11 #include "ts_xlib.h"
12 #include "ts_xutil.h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include "gdi.h"
17 #include "callback.h"
18 #include "dc.h"
19 #include "bitmap.h"
20 #include "heap.h"
21 #include "monitor.h"
22 #include "debug.h"
23 #include "xmalloc.h"
24 #include "local.h"
25 #include "x11drv.h"
26 #include "wine/winuser16.h"
27
28   /* GCs used for B&W and color bitmap operations */
29 GC BITMAP_monoGC = 0, BITMAP_colorGC = 0;
30
31
32 /***********************************************************************
33  *           X11DRV_BITMAP_Init
34  */
35 BOOL X11DRV_BITMAP_Init(void)
36 {
37     Pixmap tmpPixmap;
38     
39       /* Create the necessary GCs */
40     
41     if ((tmpPixmap = TSXCreatePixmap(display, 
42                                      X11DRV_GetXRootWindow(), 
43                                      1, 1, 
44                                      1)))
45     {
46         BITMAP_monoGC = TSXCreateGC( display, tmpPixmap, 0, NULL );
47         TSXSetGraphicsExposures( display, BITMAP_monoGC, False );
48         TSXFreePixmap( display, tmpPixmap );
49     }
50
51     if (MONITOR_GetDepth(&MONITOR_PrimaryMonitor) != 1)
52     {
53         if ((tmpPixmap = TSXCreatePixmap(display, 
54                                          X11DRV_GetXRootWindow(),
55                                          1, 1,
56                                          MONITOR_GetDepth(&MONITOR_PrimaryMonitor))))
57         {
58             BITMAP_colorGC = TSXCreateGC( display, tmpPixmap, 0, NULL );
59             TSXSetGraphicsExposures( display, BITMAP_colorGC, False );
60             TSXFreePixmap( display, tmpPixmap );
61         }
62     }
63     return TRUE;
64 }
65
66 /***********************************************************************
67  *           X11DRV_BITMAP_SelectObject
68  */
69 HBITMAP X11DRV_BITMAP_SelectObject( DC * dc, HBITMAP hbitmap,
70                                       BITMAPOBJ * bmp )
71 {
72     HRGN hrgn;
73     HBITMAP prevHandle = dc->w.hBitmap;
74     X11DRV_PHYSBITMAP *pbitmap;
75     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
76
77
78     if (!(dc->w.flags & DC_MEMORY)) return 0;
79
80     if(!bmp->DDBitmap)
81         if(!X11DRV_CreateBitmap(hbitmap))
82             return 0;
83
84     if(bmp->DDBitmap->funcs != dc->funcs) {
85         WARN(x11drv, "Trying to select non-X11 DDB into an X11 dc\n");
86         return 0;
87     }
88
89     pbitmap = bmp->DDBitmap->physBitmap;
90
91     dc->w.totalExtent.left   = 0;
92     dc->w.totalExtent.top    = 0;
93     dc->w.totalExtent.right  = bmp->bitmap.bmWidth;
94     dc->w.totalExtent.bottom = bmp->bitmap.bmHeight;
95
96     if (dc->w.hVisRgn)
97        SetRectRgn( dc->w.hVisRgn, 0, 0,
98                      bmp->bitmap.bmWidth, bmp->bitmap.bmHeight );
99     else
100     { 
101        hrgn = CreateRectRgn(0, 0, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
102        if (!hrgn) return 0;
103        dc->w.hVisRgn    = hrgn;
104     }
105
106     physDev->drawable = pbitmap->pixmap;
107     dc->w.hBitmap     = hbitmap;
108
109       /* Change GC depth if needed */
110
111     if (dc->w.bitsPerPixel != bmp->bitmap.bmBitsPixel)
112     {
113         TSXFreeGC( display, physDev->gc );
114         physDev->gc = TSXCreateGC( display, physDev->drawable, 0, NULL );
115         dc->w.bitsPerPixel = bmp->bitmap.bmBitsPixel;
116         DC_InitDC( dc );
117     }
118     else CLIPPING_UpdateGCRegion( dc );  /* Just update GC clip region */
119     return prevHandle;
120 }
121
122
123 /***********************************************************************
124  *           XPutImage_wrapper
125  *
126  * Wrapper to call XPutImage with CALL_LARGE_STACK.
127  */
128
129 struct XPutImage_descr
130 {
131     BITMAPOBJ *bmp;
132     XImage    *image;
133     INT      width;
134     INT      height;
135 };
136
137 static int XPutImage_wrapper( const struct XPutImage_descr *descr )
138 {
139     return XPutImage( display,
140                ((X11DRV_PHYSBITMAP *)descr->bmp->DDBitmap->physBitmap)->pixmap,
141                BITMAP_GC(descr->bmp),
142                descr->image, 0, 0, 0, 0, descr->width, descr->height );
143 }
144
145
146 /***************************************************************************
147  *
148  *      X11DRV_AllocBitmap
149  *
150  * Allocate DDBitmap and physBitmap
151  *
152  */
153 X11DRV_PHYSBITMAP *X11DRV_AllocBitmap( BITMAPOBJ *bmp )
154 {
155     X11DRV_PHYSBITMAP *pbitmap;
156
157     if(!(bmp->DDBitmap = HeapAlloc(GetProcessHeap(), 0, sizeof(DDBITMAP)))) {
158         WARN(x11drv, "Can't alloc DDBITMAP\n");
159         return NULL;
160     }
161
162     if(!(pbitmap = HeapAlloc(GetProcessHeap(), 0,sizeof(X11DRV_PHYSBITMAP)))) {
163         WARN(x11drv, "Can't alloc X11DRV_PHYSBITMAP\n");
164         HeapFree(GetProcessHeap(), 0, bmp->DDBitmap);
165         return NULL;
166     }
167
168     bmp->DDBitmap->physBitmap = pbitmap;
169     bmp->DDBitmap->funcs = DRIVER_FindDriver( "DISPLAY" );
170     return pbitmap;
171 }
172
173
174 /****************************************************************************
175  *
176  *        X11DRV_CreateBitmap
177  *
178  * Create a device dependent X11 bitmap
179  *
180  * Returns TRUE on success else FALSE
181  *
182  */
183
184 BOOL X11DRV_CreateBitmap( HBITMAP hbitmap )
185 {
186     X11DRV_PHYSBITMAP *pbitmap;
187     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
188
189     if(!bmp) {
190         WARN(x11drv, "Bad bitmap handle %08x\n", hbitmap);
191         return FALSE;
192     }
193
194       /* Check parameters */
195     if (bmp->bitmap.bmPlanes != 1) return 0;
196     if ((bmp->bitmap.bmBitsPixel != 1) && 
197         (bmp->bitmap.bmBitsPixel != MONITOR_GetDepth(&MONITOR_PrimaryMonitor))) {
198         ERR(x11drv, "Trying to make bitmap with planes=%d, bpp=%d\n",
199             bmp->bitmap.bmPlanes, bmp->bitmap.bmBitsPixel);
200         GDI_HEAP_UNLOCK( hbitmap );
201         return FALSE;
202     }
203
204     TRACE(x11drv, "(%08x) %dx%d %d bpp\n", hbitmap, bmp->bitmap.bmWidth,
205           bmp->bitmap.bmHeight, bmp->bitmap.bmBitsPixel);
206
207     pbitmap = X11DRV_AllocBitmap( bmp );
208     if(!pbitmap) return FALSE;
209
210       /* Create the pixmap */
211     pbitmap->pixmap = TSXCreatePixmap(display, X11DRV_GetXRootWindow(), bmp->bitmap.bmWidth,
212                               bmp->bitmap.bmHeight, bmp->bitmap.bmBitsPixel);
213     if (!pbitmap->pixmap) {
214         WARN(x11drv, "Can't create Pixmap\n");
215         HeapFree(GetProcessHeap(), 0, bmp->DDBitmap->physBitmap);
216         HeapFree(GetProcessHeap(), 0, bmp->DDBitmap);
217         GDI_HEAP_UNLOCK( hbitmap );
218         return FALSE;
219     }
220
221     if (bmp->bitmap.bmBits) /* Set bitmap bits */
222         X11DRV_BitmapBits( hbitmap, bmp->bitmap.bmBits,
223                            bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes,
224                            DDB_SET );
225
226     GDI_HEAP_UNLOCK( hbitmap );
227     return TRUE;
228 }
229
230
231 /***********************************************************************
232  *           X11DRV_BITMAP_GetXImage
233  *
234  * Get an X image for a bitmap. For use with CALL_LARGE_STACK.
235  */
236 XImage *X11DRV_BITMAP_GetXImage( const BITMAPOBJ *bmp )
237 {
238     return XGetImage( display,
239                       ((X11DRV_PHYSBITMAP *)bmp->DDBitmap->physBitmap)->pixmap,
240                       0, 0, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
241                       AllPlanes, ZPixmap );
242 }
243
244
245 /***********************************************************************
246  *           X11DRV_GetBitmapBits
247  * 
248  * RETURNS
249  *    Success: Number of bytes copied
250  *    Failure: 0
251  */
252 static LONG X11DRV_GetBitmapBits(BITMAPOBJ *bmp, void *buffer, LONG count)
253 {
254     LONG old_height, height;
255     XImage *image;
256     LPBYTE tbuf;
257     int h, w, pad;
258
259     TRACE(x11drv, "(bmp=%p, buffer=%p, count=0x%lx)\n", bmp, buffer, count);
260
261     pad = BITMAP_GetPadding(bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel);
262
263     if (pad == -1)
264         return 0;
265
266     EnterCriticalSection( &X11DRV_CritSection );
267
268     /* Hack: change the bitmap height temporarily to avoid */
269     /*       getting unnecessary bitmap rows. */
270
271     old_height = bmp->bitmap.bmHeight;
272     height = bmp->bitmap.bmHeight = count / bmp->bitmap.bmWidthBytes;
273
274     image = (XImage *)CALL_LARGE_STACK( X11DRV_BITMAP_GetXImage, bmp );
275
276     bmp->bitmap.bmHeight = old_height;
277
278     /* copy XImage to 16 bit padded image buffer with real bitsperpixel */
279
280     tbuf = buffer;
281     switch (bmp->bitmap.bmBitsPixel)
282     {
283     case 1:
284         for (h=0;h<height;h++)
285         {
286             *tbuf = 0;
287             for (w=0;w<bmp->bitmap.bmWidth;w++)
288             {
289                 if ((w%8) == 0)
290                     *tbuf = 0;
291                 *tbuf |= XGetPixel(image,w,h)<<(7-(w&7));
292                 if ((w&7) == 7) ++tbuf;
293             }
294             tbuf += pad;
295         }
296         break;
297     case 4:
298         for (h=0;h<height;h++)
299         {
300             for (w=0;w<bmp->bitmap.bmWidth;w++)
301             {
302                 if (!(w & 1)) *tbuf = XGetPixel( image, w, h) << 4;
303                 else *tbuf++ |= XGetPixel( image, w, h) & 0x0f;
304             }
305             tbuf += pad;
306         }
307         break;
308     case 8:
309         for (h=0;h<height;h++)
310         {
311             for (w=0;w<bmp->bitmap.bmWidth;w++)
312                 *tbuf++ = XGetPixel(image,w,h);
313             tbuf += pad;
314         }
315         break;
316     case 15:
317     case 16:
318         for (h=0;h<height;h++)
319         {
320             for (w=0;w<bmp->bitmap.bmWidth;w++)
321             {
322                 long pixel = XGetPixel(image,w,h);
323
324                 *tbuf++ = pixel & 0xff;
325                 *tbuf++ = (pixel>>8) & 0xff;
326             }
327         }
328         break;
329     case 24:
330         for (h=0;h<height;h++)
331         {
332             for (w=0;w<bmp->bitmap.bmWidth;w++)
333             {
334                 long pixel = XGetPixel(image,w,h);
335
336                 *tbuf++ = pixel & 0xff;
337                 *tbuf++ = (pixel>> 8) & 0xff;
338                 *tbuf++ = (pixel>>16) & 0xff;
339             }
340             tbuf += pad;
341         }
342         break;
343
344     case 32:
345         for (h=0;h<height;h++)
346         {
347             for (w=0;w<bmp->bitmap.bmWidth;w++)
348             {
349                 long pixel = XGetPixel(image,w,h);
350
351                 *tbuf++ = pixel & 0xff;
352                 *tbuf++ = (pixel>> 8) & 0xff;
353                 *tbuf++ = (pixel>>16) & 0xff;
354                 *tbuf++ = (pixel>>24) & 0xff;
355             }
356             tbuf += pad;
357         }
358         break;
359     default:
360         FIXME(x11drv, "Unhandled bits:%d\n", bmp->bitmap.bmBitsPixel);
361     }
362     XDestroyImage( image );
363     LeaveCriticalSection( &X11DRV_CritSection );
364
365     return count;
366 }
367
368
369
370 /******************************************************************************
371  *             X11DRV_SetBitmapBits
372  *
373  * RETURNS
374  *    Success: Number of bytes used in setting the bitmap bits
375  *    Failure: 0
376  */
377 static LONG X11DRV_SetBitmapBits(BITMAPOBJ *bmp, void *bits, LONG count)
378 {
379     struct XPutImage_descr descr;
380     LONG height;
381     XImage *image;
382     LPBYTE sbuf;
383     int w, h, pad;
384
385     TRACE(x11drv, "(bmp=%p, bits=%p, count=0x%lx)\n", bmp, bits, count);
386     
387     pad = BITMAP_GetPadding(bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel);
388
389     if (pad == -1) 
390         return 0;
391         
392     sbuf = (LPBYTE)bits;
393
394     height = count / bmp->bitmap.bmWidthBytes;
395
396     EnterCriticalSection( &X11DRV_CritSection );
397     image = XCreateImage( display, DefaultVisualOfScreen(X11DRV_GetXScreen()),
398                           bmp->bitmap.bmBitsPixel, ZPixmap, 0, NULL,
399                           bmp->bitmap.bmWidth, height, 32, 0 );
400     image->data = (LPBYTE)xmalloc(image->bytes_per_line * height);
401     
402     /* copy 16 bit padded image buffer with real bitsperpixel to XImage */
403     sbuf = (LPBYTE)bits;
404     switch (bmp->bitmap.bmBitsPixel)
405     {
406     case 1:
407         for (h=0;h<height;h++)
408         {
409             for (w=0;w<bmp->bitmap.bmWidth;w++)
410             {
411                 XPutPixel(image,w,h,(sbuf[0]>>(7-(w&7))) & 1);
412                 if ((w&7) == 7)
413                     sbuf++;
414             }
415             sbuf += pad;
416         }
417         break;
418     case 4:
419         for (h=0;h<height;h++)
420         {
421             for (w=0;w<bmp->bitmap.bmWidth;w++)
422             {
423                 if (!(w & 1)) XPutPixel( image, w, h, *sbuf >> 4 );
424                 else XPutPixel( image, w, h, *sbuf++ & 0xf );
425             }
426             sbuf += pad;
427         }
428         break;
429     case 8:
430         for (h=0;h<height;h++)
431         {
432             for (w=0;w<bmp->bitmap.bmWidth;w++)
433                 XPutPixel(image,w,h,*sbuf++);
434             sbuf += pad;
435         }
436         break;
437     case 15:
438     case 16:
439         for (h=0;h<height;h++)
440         {
441             for (w=0;w<bmp->bitmap.bmWidth;w++)
442             {
443                 XPutPixel(image,w,h,sbuf[1]*256+sbuf[0]);
444                 sbuf+=2;
445             }
446         }
447         break;
448     case 24: 
449         for (h=0;h<height;h++)
450         {
451             for (w=0;w<bmp->bitmap.bmWidth;w++)
452             {
453                 XPutPixel(image,w,h,(sbuf[2]<<16)+(sbuf[1]<<8)+sbuf[0]);
454                 sbuf += 3;
455             }
456             sbuf += pad;
457         }
458         break;
459     case 32: 
460         for (h=0;h<height;h++)
461         {
462             for (w=0;w<bmp->bitmap.bmWidth;w++)
463             {
464                 XPutPixel(image,w,h,(sbuf[3]<<24)+(sbuf[2]<<16)+(sbuf[1]<<8)+sbuf[0]);
465                 sbuf += 4;
466             }
467             sbuf += pad;
468         }
469         break;
470     default:
471       FIXME(x11drv, "Unhandled bits:%d\n", bmp->bitmap.bmBitsPixel);
472
473     }
474
475     descr.bmp    = bmp;
476     descr.image  = image;
477     descr.width  = bmp->bitmap.bmWidth;
478     descr.height = height;
479
480     CALL_LARGE_STACK( XPutImage_wrapper, &descr );
481     XDestroyImage( image ); /* frees image->data too */
482     LeaveCriticalSection( &X11DRV_CritSection );
483     
484     return count;
485 }
486
487 /***********************************************************************
488  *           X11DRV_BitmapBits
489  */
490 LONG X11DRV_BitmapBits(HBITMAP hbitmap, void *bits, LONG count, WORD flags)
491 {
492     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
493     LONG ret;
494     if(!bmp) {
495         WARN(x11drv, "Bad bitmap handle %08x\n", hbitmap);
496         return FALSE;
497     }
498
499     if(flags == DDB_GET)
500         ret = X11DRV_GetBitmapBits(bmp, bits, count);
501     else if(flags == DDB_SET)
502         ret = X11DRV_SetBitmapBits(bmp, bits, count);
503     else {
504         ERR(x11drv, "Unknown flags value %d\n", flags);
505         ret = 0;
506     }
507     
508     GDI_HEAP_UNLOCK( hbitmap );
509     return ret;
510 }
511
512 /***********************************************************************
513  *           X11DRV_BITMAP_DeleteObject
514  */
515 BOOL X11DRV_BITMAP_DeleteObject( HBITMAP hbitmap, BITMAPOBJ * bmp )
516 {
517     X11DRV_PHYSBITMAP *pbitmap = bmp->DDBitmap->physBitmap;
518
519     TSXFreePixmap( display, pbitmap->pixmap );
520
521     HeapFree( GetProcessHeap(), 0, bmp->DDBitmap->physBitmap );
522     HeapFree( GetProcessHeap(), 0, bmp->DDBitmap );
523     bmp->DDBitmap = NULL;
524
525     return TRUE;
526 }
527
528 #endif /* !defined(X_DISPLAY_MISSING) */