wined3d: Remove some redundant checks in the vertexdeclaration() state handler.
[wine] / dlls / winex11.drv / bitmap.c
1 /*
2  * X11DRV bitmap objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1999 Noel Borthwick
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include "windef.h"
27 #include "wingdi.h"
28 #include "wine/debug.h"
29 #include "x11drv.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
32
33   /* GCs used for B&W and color bitmap operations */
34 GC BITMAP_monoGC = 0, BITMAP_colorGC = 0;
35 X_PHYSBITMAP BITMAP_stock_phys_bitmap = { 0 };  /* phys bitmap for the default stock bitmap */
36
37 static XContext bitmap_context;  /* X context to associate a phys bitmap to a handle */
38
39 /***********************************************************************
40  *           X11DRV_BITMAP_Init
41  */
42 void X11DRV_BITMAP_Init(void)
43 {
44     Pixmap tmpPixmap;
45
46       /* Create the necessary GCs */
47
48     wine_tsx11_lock();
49     bitmap_context = XUniqueContext();
50     BITMAP_stock_phys_bitmap.pixmap_depth = 1;
51     BITMAP_stock_phys_bitmap.pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, 1 );
52     BITMAP_monoGC = XCreateGC( gdi_display, BITMAP_stock_phys_bitmap.pixmap, 0, NULL );
53     XSetGraphicsExposures( gdi_display, BITMAP_monoGC, False );
54     XSetSubwindowMode( gdi_display, BITMAP_monoGC, IncludeInferiors );
55
56     if (screen_depth != 1)
57     {
58         if ((tmpPixmap = XCreatePixmap( gdi_display, root_window, 1, 1, screen_depth )))
59         {
60             BITMAP_colorGC = XCreateGC( gdi_display, tmpPixmap, 0, NULL );
61             XSetGraphicsExposures( gdi_display, BITMAP_colorGC, False );
62             XSetSubwindowMode( gdi_display, BITMAP_colorGC, IncludeInferiors );
63             XFreePixmap( gdi_display, tmpPixmap );
64         }
65     }
66     wine_tsx11_unlock();
67 }
68
69 /***********************************************************************
70  *           SelectBitmap   (X11DRV.@)
71  */
72 HBITMAP X11DRV_SelectBitmap( X11DRV_PDEVICE *physDev, HBITMAP hbitmap )
73 {
74     X_PHYSBITMAP *physBitmap;
75     BITMAP bitmap;
76
77     if (!GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return 0;
78
79     if(physDev->xrender)
80         X11DRV_XRender_UpdateDrawable( physDev );
81
82     if (hbitmap == BITMAP_stock_phys_bitmap.hbitmap) physBitmap = &BITMAP_stock_phys_bitmap;
83     else if (!(physBitmap = X11DRV_get_phys_bitmap( hbitmap ))) return 0;
84
85     physDev->bitmap = physBitmap;
86     physDev->drawable = physBitmap->pixmap;
87     SetRect( &physDev->drawable_rect, 0, 0, bitmap.bmWidth, bitmap.bmHeight );
88     physDev->dc_rect = physDev->drawable_rect;
89
90       /* Change GC depth if needed */
91
92     if (physDev->depth != physBitmap->pixmap_depth)
93     {
94         physDev->depth = physBitmap->pixmap_depth;
95         wine_tsx11_lock();
96         XFreeGC( gdi_display, physDev->gc );
97         physDev->gc = XCreateGC( gdi_display, physDev->drawable, 0, NULL );
98         XSetGraphicsExposures( gdi_display, physDev->gc, False );
99         XSetSubwindowMode( gdi_display, physDev->gc, IncludeInferiors );
100         XFlush( gdi_display );
101         wine_tsx11_unlock();
102     }
103     return hbitmap;
104 }
105
106
107 /****************************************************************************
108  *        CreateBitmap   (X11DRV.@)
109  *
110  * Create a device dependent X11 bitmap
111  *
112  * Returns TRUE on success else FALSE
113  */
114 BOOL X11DRV_CreateBitmap( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, LPVOID bmBits )
115 {
116     X_PHYSBITMAP *physBitmap;
117     BITMAP bitmap;
118
119     if (!GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return FALSE;
120
121       /* Check parameters */
122     if (bitmap.bmPlanes != 1) return FALSE;
123
124     if ((bitmap.bmBitsPixel != 1) && (bitmap.bmBitsPixel != screen_depth))
125     {
126         ERR("Trying to make bitmap with planes=%d, bpp=%d\n",
127             bitmap.bmPlanes, bitmap.bmBitsPixel);
128         return FALSE;
129     }
130     if (hbitmap == BITMAP_stock_phys_bitmap.hbitmap)
131     {
132         ERR( "called for stock bitmap, please report\n" );
133         return FALSE;
134     }
135
136     TRACE("(%p) %dx%d %d bpp\n", hbitmap, bitmap.bmWidth, bitmap.bmHeight, bitmap.bmBitsPixel);
137
138     if (!(physBitmap = X11DRV_init_phys_bitmap( hbitmap ))) return FALSE;
139
140       /* Create the pixmap */
141     wine_tsx11_lock();
142     physBitmap->pixmap_depth = bitmap.bmBitsPixel;
143     physBitmap->pixmap = XCreatePixmap(gdi_display, root_window,
144                                        bitmap.bmWidth, bitmap.bmHeight, bitmap.bmBitsPixel);
145     wine_tsx11_unlock();
146     if (!physBitmap->pixmap)
147     {
148         WARN("Can't create Pixmap\n");
149         HeapFree( GetProcessHeap(), 0, physBitmap );
150         return FALSE;
151     }
152
153     if (bmBits) /* Set bitmap bits */
154     {
155         X11DRV_SetBitmapBits( hbitmap, bmBits, bitmap.bmHeight * bitmap.bmWidthBytes );
156     }
157     else  /* else clear the bitmap */
158     {
159         wine_tsx11_lock();
160         XSetFunction( gdi_display, BITMAP_GC(physBitmap), GXclear );
161         XFillRectangle( gdi_display, physBitmap->pixmap, BITMAP_GC(physBitmap), 0, 0,
162                         bitmap.bmWidth, bitmap.bmHeight );
163         XSetFunction( gdi_display, BITMAP_GC(physBitmap), GXcopy );
164         wine_tsx11_unlock();
165     }
166     return TRUE;
167 }
168
169
170 /***********************************************************************
171  *           GetBitmapBits   (X11DRV.@)
172  *
173  * RETURNS
174  *    Success: Number of bytes copied
175  *    Failure: 0
176  */
177 LONG X11DRV_GetBitmapBits( HBITMAP hbitmap, void *buffer, LONG count )
178 {
179     BITMAP bitmap;
180     X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
181     LONG old_height, height;
182     XImage *image;
183     LPBYTE tbuf, startline;
184     int h, w;
185
186     if (!physBitmap || !GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return 0;
187
188     TRACE("(bmp=%p, buffer=%p, count=0x%x)\n", hbitmap, buffer, count);
189
190     wine_tsx11_lock();
191
192     /* Hack: change the bitmap height temporarily to avoid */
193     /*       getting unnecessary bitmap rows. */
194
195     old_height = bitmap.bmHeight;
196     height = bitmap.bmHeight = count / bitmap.bmWidthBytes;
197
198     image = XGetImage( gdi_display, physBitmap->pixmap, 0, 0,
199                        bitmap.bmWidth, bitmap.bmHeight, AllPlanes, ZPixmap );
200     bitmap.bmHeight = old_height;
201
202     /* copy XImage to 16 bit padded image buffer with real bitsperpixel */
203
204     startline = buffer;
205     switch (physBitmap->pixmap_depth)
206     {
207     case 1:
208         for (h=0;h<height;h++)
209         {
210             tbuf = startline;
211             *tbuf = 0;
212             for (w=0;w<bitmap.bmWidth;w++)
213             {
214                 if ((w%8) == 0)
215                     *tbuf = 0;
216                 *tbuf |= XGetPixel(image,w,h)<<(7-(w&7));
217                 if ((w&7) == 7) ++tbuf;
218             }
219             startline += bitmap.bmWidthBytes;
220         }
221         break;
222     case 4:
223         for (h=0;h<height;h++)
224         {
225             tbuf = startline;
226             for (w=0;w<bitmap.bmWidth;w++)
227             {
228                 if (!(w & 1)) *tbuf = XGetPixel( image, w, h) << 4;
229                 else *tbuf++ |= XGetPixel( image, w, h) & 0x0f;
230             }
231             startline += bitmap.bmWidthBytes;
232         }
233         break;
234     case 8:
235         for (h=0;h<height;h++)
236         {
237             tbuf = startline;
238             for (w=0;w<bitmap.bmWidth;w++)
239                 *tbuf++ = XGetPixel(image,w,h);
240             startline += bitmap.bmWidthBytes;
241         }
242         break;
243     case 15:
244     case 16:
245         for (h=0;h<height;h++)
246         {
247             tbuf = startline;
248             for (w=0;w<bitmap.bmWidth;w++)
249             {
250                 long pixel = XGetPixel(image,w,h);
251
252                 *tbuf++ = pixel & 0xff;
253                 *tbuf++ = (pixel>>8) & 0xff;
254             }
255             startline += bitmap.bmWidthBytes;
256         }
257         break;
258     case 24:
259         for (h=0;h<height;h++)
260         {
261             tbuf = startline;
262             for (w=0;w<bitmap.bmWidth;w++)
263             {
264                 long pixel = XGetPixel(image,w,h);
265
266                 *tbuf++ = pixel & 0xff;
267                 *tbuf++ = (pixel>> 8) & 0xff;
268                 *tbuf++ = (pixel>>16) & 0xff;
269             }
270             startline += bitmap.bmWidthBytes;
271         }
272         break;
273
274     case 32:
275         for (h=0;h<height;h++)
276         {
277             tbuf = startline;
278             for (w=0;w<bitmap.bmWidth;w++)
279             {
280                 long pixel = XGetPixel(image,w,h);
281
282                 *tbuf++ = pixel & 0xff;
283                 *tbuf++ = (pixel>> 8) & 0xff;
284                 *tbuf++ = (pixel>>16) & 0xff;
285                 *tbuf++ = (pixel>>24) & 0xff;
286             }
287             startline += bitmap.bmWidthBytes;
288         }
289         break;
290     default:
291         FIXME("Unhandled bits:%d\n", physBitmap->pixmap_depth);
292     }
293     XDestroyImage( image );
294     wine_tsx11_unlock();
295     return count;
296 }
297
298
299
300 /******************************************************************************
301  *             SetBitmapBits   (X11DRV.@)
302  *
303  * RETURNS
304  *    Success: Number of bytes used in setting the bitmap bits
305  *    Failure: 0
306  */
307 LONG X11DRV_SetBitmapBits( HBITMAP hbitmap, const void *bits, LONG count )
308 {
309     BITMAP bitmap;
310     X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
311     LONG height;
312     XImage *image;
313     const BYTE *sbuf, *startline;
314     int w, h;
315
316     if (!physBitmap || !GetObjectW( hbitmap, sizeof(bitmap), &bitmap )) return 0;
317
318     TRACE("(bmp=%p, bits=%p, count=0x%x)\n", hbitmap, bits, count);
319
320     height = count / bitmap.bmWidthBytes;
321
322     wine_tsx11_lock();
323     image = XCreateImage( gdi_display, visual, physBitmap->pixmap_depth, ZPixmap, 0, NULL,
324                           bitmap.bmWidth, height, 32, 0 );
325     if (!(image->data = malloc(image->bytes_per_line * height)))
326     {
327         WARN("No memory to create image data.\n");
328         XDestroyImage( image );
329         wine_tsx11_unlock();
330         return 0;
331     }
332
333     /* copy 16 bit padded image buffer with real bitsperpixel to XImage */
334
335     startline = bits;
336
337     switch (physBitmap->pixmap_depth)
338     {
339     case 1:
340         for (h=0;h<height;h++)
341         {
342             sbuf = startline;
343             for (w=0;w<bitmap.bmWidth;w++)
344             {
345                 XPutPixel(image,w,h,(sbuf[0]>>(7-(w&7))) & 1);
346                 if ((w&7) == 7)
347                     sbuf++;
348             }
349             startline += bitmap.bmWidthBytes;
350         }
351         break;
352     case 4:
353         for (h=0;h<height;h++)
354         {
355             sbuf = startline;
356             for (w=0;w<bitmap.bmWidth;w++)
357             {
358                 if (!(w & 1)) XPutPixel( image, w, h, *sbuf >> 4 );
359                 else XPutPixel( image, w, h, *sbuf++ & 0xf );
360             }
361             startline += bitmap.bmWidthBytes;
362         }
363         break;
364     case 8:
365         for (h=0;h<height;h++)
366         {
367             sbuf = startline;
368             for (w=0;w<bitmap.bmWidth;w++)
369                 XPutPixel(image,w,h,*sbuf++);
370             startline += bitmap.bmWidthBytes;
371         }
372         break;
373     case 15:
374     case 16:
375         for (h=0;h<height;h++)
376         {
377             sbuf = startline;
378             for (w=0;w<bitmap.bmWidth;w++)
379             {
380                 XPutPixel(image,w,h,sbuf[1]*256+sbuf[0]);
381                 sbuf+=2;
382             }
383             startline += bitmap.bmWidthBytes;
384         }
385         break;
386     case 24:
387         for (h=0;h<height;h++)
388         {
389             sbuf = startline;
390             for (w=0;w<bitmap.bmWidth;w++)
391             {
392                 XPutPixel(image,w,h,(sbuf[2]<<16)+(sbuf[1]<<8)+sbuf[0]);
393                 sbuf += 3;
394             }
395             startline += bitmap.bmWidthBytes;
396         }
397         break;
398     case 32:
399         for (h=0;h<height;h++)
400         {
401             sbuf = startline;
402             for (w=0;w<bitmap.bmWidth;w++)
403             {
404                 XPutPixel(image,w,h,(sbuf[3]<<24)+(sbuf[2]<<16)+(sbuf[1]<<8)+sbuf[0]);
405                 sbuf += 4;
406             }
407             startline += bitmap.bmWidthBytes;
408         }
409         break;
410     default:
411       FIXME("Unhandled bits:%d\n", physBitmap->pixmap_depth);
412
413     }
414     XPutImage( gdi_display, physBitmap->pixmap, BITMAP_GC(physBitmap),
415                image, 0, 0, 0, 0, bitmap.bmWidth, height );
416     XDestroyImage( image ); /* frees image->data too */
417     wine_tsx11_unlock();
418     return count;
419 }
420
421 /***********************************************************************
422  *           DeleteBitmap   (X11DRV.@)
423  */
424 BOOL X11DRV_DeleteBitmap( HBITMAP hbitmap )
425 {
426     X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
427
428     if (physBitmap)
429     {
430         DIBSECTION dib;
431
432         if (GetObjectW( hbitmap, sizeof(dib), &dib ) == sizeof(dib))
433             X11DRV_DIB_DeleteDIBSection( physBitmap, &dib );
434
435         if (physBitmap->glxpixmap) destroy_glxpixmap(physBitmap->glxpixmap); 
436         wine_tsx11_lock();
437         if (physBitmap->pixmap) XFreePixmap( gdi_display, physBitmap->pixmap );
438         XDeleteContext( gdi_display, (XID)hbitmap, bitmap_context );
439         wine_tsx11_unlock();
440         HeapFree( GetProcessHeap(), 0, physBitmap );
441     }
442     return TRUE;
443 }
444
445
446 /***********************************************************************
447  *           X11DRV_get_phys_bitmap
448  *
449  * Retrieve the X physical bitmap info.
450  */
451 X_PHYSBITMAP *X11DRV_get_phys_bitmap( HBITMAP hbitmap )
452 {
453     X_PHYSBITMAP *ret;
454
455     wine_tsx11_lock();
456     if (XFindContext( gdi_display, (XID)hbitmap, bitmap_context, (char **)&ret )) ret = NULL;
457     wine_tsx11_unlock();
458     return ret;
459 }
460
461
462 /***********************************************************************
463  *           X11DRV_init_phys_bitmap
464  *
465  * Initialize the X physical bitmap info.
466  */
467 X_PHYSBITMAP *X11DRV_init_phys_bitmap( HBITMAP hbitmap )
468 {
469     X_PHYSBITMAP *ret;
470
471     if ((ret = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret) )) != NULL)
472     {
473         ret->hbitmap = hbitmap;
474         wine_tsx11_lock();
475         XSaveContext( gdi_display, (XID)hbitmap, bitmap_context, (char *)ret );
476         wine_tsx11_unlock();
477     }
478     return ret;
479 }
480
481
482 /***********************************************************************
483  *           X11DRV_get_pixmap
484  *
485  * Retrieve the pixmap associated to a bitmap.
486  */
487 Pixmap X11DRV_get_pixmap( HBITMAP hbitmap )
488 {
489     X_PHYSBITMAP *physBitmap = X11DRV_get_phys_bitmap( hbitmap );
490
491     if (!physBitmap) return 0;
492     return physBitmap->pixmap;
493 }