Fix changelog email address
[freerdp-ubuntu-pcb-backport.git] / client / X11 / xf_gdi.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * X11 GDI
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22
23 #include <freerdp/gdi/gdi.h>
24 #include <freerdp/codec/rfx.h>
25 #include <freerdp/codec/nsc.h>
26 #include <freerdp/constants.h>
27 #include <freerdp/utils/memory.h>
28 #include <freerdp/codec/color.h>
29 #include <freerdp/codec/bitmap.h>
30
31 #include "xf_gdi.h"
32
33 static const uint8 xf_rop2_table[] =
34 {
35         0,
36         GXclear,        /* 0 */
37         GXnor,          /* DPon */
38         GXandInverted,  /* DPna */
39         GXcopyInverted, /* Pn */
40         GXandReverse,   /* PDna */
41         GXinvert,       /* Dn */
42         GXxor,          /* DPx */
43         GXnand,         /* DPan */
44         GXand,          /* DPa */
45         GXequiv,        /* DPxn */
46         GXnoop,         /* D */
47         GXorInverted,   /* DPno */
48         GXcopy,         /* P */
49         GXorReverse,    /* PDno */
50         GXor,           /* DPo */
51         GXset           /* 1 */
52 };
53
54 boolean xf_set_rop2(xfInfo* xfi, int rop2)
55 {
56         if ((rop2 < 0x01) || (rop2 > 0x10))
57         {
58                 printf("Unsupported ROP2: %d\n", rop2);
59                 return false;
60         }
61
62         XSetFunction(xfi->display, xfi->gc, xf_rop2_table[rop2]);
63         return true;
64 }
65
66 boolean xf_set_rop3(xfInfo* xfi, int rop3)
67 {
68         int function = -1;
69
70         switch (rop3)
71         {
72                 case GDI_BLACKNESS:
73                         function = GXclear;
74                         break;
75
76                 case 0x000500A9:
77                         function = GXnor;
78                         break;
79
80                 case 0x000A0329:
81                         function = GXandInverted;
82                         break;
83
84                 case 0x000F0001:
85                         function = GXcopyInverted;
86                         break;
87
88                 case GDI_NOTSRCERASE:
89                         function = GXnor;
90                         break;
91
92                 case GDI_DSna:
93                         function = GXandInverted;
94                         break;
95
96                 case GDI_NOTSRCCOPY:
97                         function = GXcopyInverted;
98                         break;
99
100                 case GDI_SRCERASE:
101                         function = GXandReverse;
102                         break;
103
104                 case 0x00500325:
105                         function = GXandReverse;
106                         break;
107
108                 case GDI_DSTINVERT:
109                         function = GXinvert;
110                         break;
111
112                 case GDI_PATINVERT:
113                         function = GXxor;
114                         break;
115
116                 case 0x005F00E9:
117                         function = GXnand;
118                         break;
119
120                 case GDI_SRCINVERT:
121                         function = GXxor;
122                         break;
123
124                 case 0x007700E6:
125                         function = GXnand;
126                         break;
127
128                 case GDI_SRCAND:
129                         function = GXand;
130                         break;
131
132                 case 0x00990066:
133                         function = GXequiv;
134                         break;
135
136                 case 0x00A000C9:
137                         function = GXand;
138                         break;
139
140                 case GDI_PDxn:
141                         function = GXequiv;
142                         break;
143
144                 case 0x00AA0029:
145                         function = GXnoop;
146                         break;
147
148                 case 0x00AF0229:
149                         function = GXorInverted;
150                         break;
151
152                 case GDI_MERGEPAINT:
153                         function = GXorInverted;
154                         break;
155
156                 case GDI_SRCCOPY:
157                         function = GXcopy;
158                         break;
159
160                 case 0x00DD0228:
161                         function = GXorReverse;
162                         break;
163
164                 case GDI_SRCPAINT:
165                         function = GXor;
166                         break;
167
168                 case GDI_PATCOPY:
169                         function = GXcopy;
170                         break;
171
172                 case 0x00F50225:
173                         function = GXorReverse;
174                         break;
175
176                 case 0x00FA0089:
177                         function = GXor;
178                         break;
179
180                 case GDI_WHITENESS:
181                         function = GXset;
182                         break;
183
184                 default:
185                         break;
186         }
187
188         if (function < 0)
189         {
190                 printf("Unsupported ROP3: 0x%08X\n", rop3);
191                 XSetFunction(xfi->display, xfi->gc, GXclear);
192                 return false;
193         }
194
195         XSetFunction(xfi->display, xfi->gc, function);
196
197         return true;
198 }
199
200 Pixmap xf_brush_new(xfInfo* xfi, int width, int height, int bpp, uint8* data)
201 {
202         Pixmap bitmap;
203         uint8* cdata;
204         XImage* image;
205
206         bitmap = XCreatePixmap(xfi->display, xfi->drawable, width, height, xfi->depth);
207
208         if(data != NULL)
209         {
210                 GC gc;  // FIXME, should cache
211
212                 cdata = freerdp_image_convert(data, NULL, width, height, bpp, xfi->bpp, xfi->clrconv);
213                 image = XCreateImage(xfi->display, xfi->visual, xfi->depth,
214                                                 ZPixmap, 0, (char*) cdata, width, height, xfi->scanline_pad, 0);
215
216                 gc = XCreateGC(xfi->display, xfi->drawable, 0, NULL);
217                 XPutImage(xfi->display, bitmap, gc, image, 0, 0, 0, 0, width, height);
218                 XFree(image);
219                 if (cdata != data)
220                         xfree(cdata);
221
222                 XFreeGC(xfi->display, gc);
223         }
224
225         return bitmap;
226 }
227
228 Pixmap xf_mono_bitmap_new(xfInfo* xfi, int width, int height, uint8* data)
229 {
230         int scanline;
231         XImage* image;
232         Pixmap bitmap;
233
234         scanline = (width + 7) / 8;
235
236         bitmap = XCreatePixmap(xfi->display, xfi->drawable, width, height, 1);
237
238         image = XCreateImage(xfi->display, xfi->visual, 1,
239                         ZPixmap, 0, (char*) data, width, height, 8, scanline);
240
241         XPutImage(xfi->display, bitmap, xfi->gc_mono, image, 0, 0, 0, 0, width, height);
242         XFree(image);
243
244         return bitmap;
245 }
246
247 Pixmap xf_glyph_new(xfInfo* xfi, int width, int height, uint8* data)
248 {
249         int scanline;
250         Pixmap bitmap;
251         XImage* image;
252
253         scanline = (width + 7) / 8;
254
255         bitmap = XCreatePixmap(xfi->display, xfi->drawable, width, height, 1);
256
257         image = XCreateImage(xfi->display, xfi->visual, 1,
258                         ZPixmap, 0, (char*) data, width, height, 8, scanline);
259
260         image->byte_order = MSBFirst;
261         image->bitmap_bit_order = MSBFirst;
262
263         XInitImage(image);
264         XPutImage(xfi->display, bitmap, xfi->gc_mono, image, 0, 0, 0, 0, width, height);
265         XFree(image);
266
267         return bitmap;
268 }
269
270 void xf_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
271 {
272         xfInfo* xfi = ((xfContext*) context)->xfi;
273         xfi->clrconv->palette->count = palette->number;
274         xfi->clrconv->palette->entries = palette->entries;
275 }
276
277 void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
278 {
279         XRectangle clip;
280         xfInfo* xfi = ((xfContext*) context)->xfi;
281
282         if (bounds != NULL)
283         {
284                 clip.x = bounds->left;
285                 clip.y = bounds->top;
286                 clip.width = bounds->right - bounds->left + 1;
287                 clip.height = bounds->bottom - bounds->top + 1;
288                 XSetClipRectangles(xfi->display, xfi->gc, 0, 0, &clip, 1, YXBanded);
289         }
290         else
291         {
292                 XSetClipMask(xfi->display, xfi->gc, None);
293         }
294 }
295
296 void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt)
297 {
298         xfInfo* xfi = ((xfContext*) context)->xfi;
299
300         xf_set_rop3(xfi, gdi_rop3_code(dstblt->bRop));
301
302         XSetFillStyle(xfi->display, xfi->gc, FillSolid);
303         XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
304                         dstblt->nLeftRect, dstblt->nTopRect,
305                         dstblt->nWidth, dstblt->nHeight);
306
307         if (xfi->drawing == xfi->primary)
308         {
309                 if (xfi->remote_app != true)
310                 {
311                         XFillRectangle(xfi->display, xfi->drawable, xfi->gc,
312                                 dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight);
313                 }
314
315                 gdi_InvalidateRegion(xfi->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight);
316         }
317         XSetFunction(xfi->display, xfi->gc, GXcopy);
318 }
319
320 void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
321 {
322         Pixmap pattern;
323         rdpBrush* brush;
324         uint32 foreColor;
325         uint32 backColor;
326         xfInfo* xfi = ((xfContext*) context)->xfi;
327
328         brush = &patblt->brush;
329         xf_set_rop3(xfi, gdi_rop3_code(patblt->bRop));
330
331         foreColor = freerdp_color_convert_rgb(patblt->foreColor, xfi->srcBpp, 32, xfi->clrconv);
332         backColor = freerdp_color_convert_rgb(patblt->backColor, xfi->srcBpp, 32, xfi->clrconv);
333
334         if (brush->style == GDI_BS_SOLID)
335         {
336                 XSetFillStyle(xfi->display, xfi->gc, FillSolid);
337                 XSetForeground(xfi->display, xfi->gc, foreColor);
338
339                 XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
340                                 patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight);
341         }
342         else if (brush->style == GDI_BS_PATTERN)
343         {
344                 if (brush->bpp > 1)
345                 {
346                         pattern = xf_brush_new(xfi, 8, 8, brush->bpp, brush->data);
347
348                         XSetFillStyle(xfi->display, xfi->gc, FillTiled);
349                         XSetTile(xfi->display, xfi->gc, pattern);
350                         XSetTSOrigin(xfi->display, xfi->gc, brush->x, brush->y);
351
352                         XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
353                                         patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight);
354
355                         XSetTile(xfi->display, xfi->gc, xfi->primary);
356
357                         XFreePixmap(xfi->display, pattern);
358                 }
359                 else
360                 {
361                         pattern = xf_mono_bitmap_new(xfi, 8, 8, brush->data);
362
363                         XSetForeground(xfi->display, xfi->gc, backColor);
364                         XSetBackground(xfi->display, xfi->gc, foreColor);
365                         XSetFillStyle(xfi->display, xfi->gc, FillOpaqueStippled);
366                         XSetStipple(xfi->display, xfi->gc, pattern);
367                         XSetTSOrigin(xfi->display, xfi->gc, brush->x, brush->y);
368
369                         XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
370                                         patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight);
371
372                         XFreePixmap(xfi->display, pattern);
373                 }
374         }
375         else
376         {
377                 printf("unimplemented brush style:%d\n", brush->style);
378         }
379
380         if (xfi->drawing == xfi->primary)
381         {
382                 XSetFunction(xfi->display, xfi->gc, GXcopy);
383
384                 if (xfi->remote_app != true)
385                 {
386                         XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc, patblt->nLeftRect, patblt->nTopRect,
387                                 patblt->nWidth, patblt->nHeight, patblt->nLeftRect, patblt->nTopRect);
388                 }
389
390                 gdi_InvalidateRegion(xfi->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight);
391         }
392
393         XSetFunction(xfi->display, xfi->gc, GXcopy);
394 }
395
396 void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
397 {
398         xfInfo* xfi = ((xfContext*) context)->xfi;
399
400         xf_set_rop3(xfi, gdi_rop3_code(scrblt->bRop));
401
402         XCopyArea(xfi->display, xfi->primary, xfi->drawing, xfi->gc, scrblt->nXSrc, scrblt->nYSrc,
403                         scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect);
404
405         if (xfi->drawing == xfi->primary)
406         {
407                 if (xfi->remote_app != true)
408                 {
409                         if (xfi->unobscured)
410                         {
411                                 XCopyArea(xfi->display, xfi->drawable, xfi->drawable, xfi->gc,
412                                                 scrblt->nXSrc, scrblt->nYSrc, scrblt->nWidth, scrblt->nHeight,
413                                                 scrblt->nLeftRect, scrblt->nTopRect);
414                         }
415                         else
416                         {
417                                 XSetFunction(xfi->display, xfi->gc, GXcopy);
418                                 XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc,
419                                                 scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight,
420                                                 scrblt->nLeftRect, scrblt->nTopRect);
421                         }
422                 }
423
424                 gdi_InvalidateRegion(xfi->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight);
425         }
426
427         XSetFunction(xfi->display, xfi->gc, GXcopy);
428 }
429
430 void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
431 {
432         uint32 color;
433         xfInfo* xfi = ((xfContext*) context)->xfi;
434
435         color = freerdp_color_convert_var(opaque_rect->color, xfi->srcBpp, 32, xfi->clrconv);
436
437         XSetFunction(xfi->display, xfi->gc, GXcopy);
438         XSetFillStyle(xfi->display, xfi->gc, FillSolid);
439         XSetForeground(xfi->display, xfi->gc, color);
440
441         XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
442                         opaque_rect->nLeftRect, opaque_rect->nTopRect,
443                         opaque_rect->nWidth, opaque_rect->nHeight);
444
445         if (xfi->drawing == xfi->primary)
446         {
447                 if (xfi->remote_app != true)
448                 {
449                         XFillRectangle(xfi->display, xfi->drawable, xfi->gc,
450                                 opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight);
451                 }
452
453                 gdi_InvalidateRegion(xfi->hdc, opaque_rect->nLeftRect, opaque_rect->nTopRect,
454                                 opaque_rect->nWidth, opaque_rect->nHeight);
455         }
456 }
457
458 void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
459 {
460         int i;
461         uint32 color;
462         DELTA_RECT* rectangle;
463         xfInfo* xfi = ((xfContext*) context)->xfi;
464
465         color = freerdp_color_convert_var(multi_opaque_rect->color, xfi->srcBpp, 32, xfi->clrconv);
466
467         XSetFunction(xfi->display, xfi->gc, GXcopy);
468         XSetFillStyle(xfi->display, xfi->gc, FillSolid);
469         XSetForeground(xfi->display, xfi->gc, color);
470
471         for (i = 1; i < multi_opaque_rect->numRectangles + 1; i++)
472         {
473                 rectangle = &multi_opaque_rect->rectangles[i];
474
475                 XFillRectangle(xfi->display, xfi->drawing, xfi->gc,
476                                 rectangle->left, rectangle->top,
477                                 rectangle->width, rectangle->height);
478
479                 if (xfi->drawing == xfi->primary)
480                 {
481                         if (xfi->remote_app != true)
482                         {
483                                 XFillRectangle(xfi->display, xfi->drawable, xfi->gc,
484                                         rectangle->left, rectangle->top, rectangle->width, rectangle->height);
485                         }
486
487                         gdi_InvalidateRegion(xfi->hdc, rectangle->left, rectangle->top, rectangle->width, rectangle->height);
488                 }
489         }
490 }
491
492 void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
493 {
494         uint32 color;
495         xfInfo* xfi = ((xfContext*) context)->xfi;
496
497         xf_set_rop2(xfi, line_to->bRop2);
498         color = freerdp_color_convert_rgb(line_to->penColor, xfi->srcBpp, 32, xfi->clrconv);
499
500         XSetFillStyle(xfi->display, xfi->gc, FillSolid);
501         XSetForeground(xfi->display, xfi->gc, color);
502
503         XDrawLine(xfi->display, xfi->drawing, xfi->gc,
504                         line_to->nXStart, line_to->nYStart, line_to->nXEnd, line_to->nYEnd);
505
506         if (xfi->drawing == xfi->primary)
507         {
508                 int width, height;
509
510                 if (xfi->remote_app != true)
511                 {
512                         XDrawLine(xfi->display, xfi->drawable, xfi->gc,
513                                 line_to->nXStart, line_to->nYStart, line_to->nXEnd, line_to->nYEnd);
514                 }
515
516                 width = line_to->nXStart - line_to->nXEnd;
517                 height = line_to->nYStart - line_to->nYEnd;
518
519                 if (width < 0)
520                         width *= (-1);
521
522                 if (height < 0)
523                         height *= (-1);
524
525                 gdi_InvalidateRegion(xfi->hdc, line_to->nXStart, line_to->nYStart, width, height);
526
527         }
528
529         XSetFunction(xfi->display, xfi->gc, GXcopy);
530 }
531
532 void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
533 {
534         int i;
535         int x, y;
536         int x1, y1;
537         int x2, y2;
538         int npoints;
539         uint32 color;
540         XPoint* points;
541         int width, height;
542         xfInfo* xfi = ((xfContext*) context)->xfi;
543
544         xf_set_rop2(xfi, polyline->bRop2);
545         color = freerdp_color_convert_rgb(polyline->penColor, xfi->srcBpp, 32, xfi->clrconv);
546
547         XSetFillStyle(xfi->display, xfi->gc, FillSolid);
548         XSetForeground(xfi->display, xfi->gc, color);
549
550         npoints = polyline->numPoints + 1;
551         points = xmalloc(sizeof(XPoint) * npoints);
552
553         points[0].x = polyline->xStart;
554         points[0].y = polyline->yStart;
555
556         for (i = 0; i < polyline->numPoints; i++)
557         {
558                 points[i + 1].x = polyline->points[i].x;
559                 points[i + 1].y = polyline->points[i].y;
560         }
561
562         XDrawLines(xfi->display, xfi->drawing, xfi->gc, points, npoints, CoordModePrevious);
563
564         if (xfi->drawing == xfi->primary)
565         {
566                 if (xfi->remote_app != true)
567                         XDrawLines(xfi->display, xfi->drawable, xfi->gc, points, npoints, CoordModePrevious);
568
569                 x1 = points[0].x;
570                 y1 = points[0].y;
571
572                 for (i = 1; i < npoints; i++)
573                 {
574                         x2 = points[i].x + x1;
575                         y2 = points[i].y + y1;
576
577                         x = (x2 < x1) ? x2 : x1;
578                         width = (x2 > x1) ? x2 - x1 : x1 - x2;
579
580                         y = (y2 < y1) ? y2 : y1;
581                         height = (y2 > y1) ? y2 - y1 : y1 - y2;
582
583                         x1 = x2;
584                         y1 = y2;
585
586                         gdi_InvalidateRegion(xfi->hdc, x, y, width, height);
587                 }
588         }
589
590         XSetFunction(xfi->display, xfi->gc, GXcopy);
591         xfree(points);
592 }
593
594 void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
595 {
596         xfBitmap* bitmap;
597         xfInfo* xfi = ((xfContext*) context)->xfi;
598
599         bitmap = (xfBitmap*) memblt->bitmap;
600         xf_set_rop3(xfi, gdi_rop3_code(memblt->bRop));
601
602         XCopyArea(xfi->display, bitmap->pixmap, xfi->drawing, xfi->gc,
603                         memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight,
604                         memblt->nLeftRect, memblt->nTopRect);
605
606         if (xfi->drawing == xfi->primary)
607         {
608                 if (xfi->remote_app != true)
609                 {
610                         XCopyArea(xfi->display, bitmap->pixmap, xfi->drawable, xfi->gc,
611                                 memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight,
612                                 memblt->nLeftRect, memblt->nTopRect);
613                 }
614
615                 gdi_InvalidateRegion(xfi->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight);
616         }
617
618         XSetFunction(xfi->display, xfi->gc, GXcopy);
619 }
620
621 void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
622 {
623
624 }
625
626 void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
627 {
628
629 }
630
631 void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command)
632 {
633         int i, tx, ty;
634         XImage* image;
635         RFX_MESSAGE* message;
636         xfInfo* xfi = ((xfContext*) context)->xfi;
637         RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) xfi->rfx_context;
638         NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) xfi->nsc_context;
639
640         if (surface_bits_command->codecID == CODEC_ID_REMOTEFX)
641         {
642                 message = rfx_process_message(rfx_context,
643                                 surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
644
645                 XSetFunction(xfi->display, xfi->gc, GXcopy);
646                 XSetFillStyle(xfi->display, xfi->gc, FillSolid);
647
648                 XSetClipRectangles(xfi->display, xfi->gc,
649                                 surface_bits_command->destLeft, surface_bits_command->destTop,
650                                 (XRectangle*) message->rects, message->num_rects, YXBanded);
651
652                 /* Draw the tiles to primary surface, each is 64x64. */
653                 for (i = 0; i < message->num_tiles; i++)
654                 {
655                         image = XCreateImage(xfi->display, xfi->visual, 24, ZPixmap, 0,
656                                 (char*) message->tiles[i]->data, 64, 64, 32, 0);
657
658                         tx = message->tiles[i]->x + surface_bits_command->destLeft;
659                         ty = message->tiles[i]->y + surface_bits_command->destTop;
660
661                         XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0, tx, ty, 64, 64);
662                         XFree(image);
663                 }
664
665                 /* Copy the updated region from backstore to the window. */
666                 for (i = 0; i < message->num_rects; i++)
667                 {
668                         tx = message->rects[i].x + surface_bits_command->destLeft;
669                         ty = message->rects[i].y + surface_bits_command->destTop;
670
671                         if (xfi->remote_app != true)
672                         {
673                                 XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc,
674                                                 tx, ty, message->rects[i].width, message->rects[i].height, tx, ty);
675                         }
676
677                         gdi_InvalidateRegion(xfi->hdc, tx, ty, message->rects[i].width, message->rects[i].height);
678                 }
679
680                 XSetClipMask(xfi->display, xfi->gc, None);
681                 rfx_message_free(rfx_context, message);
682         }
683         else if (surface_bits_command->codecID == CODEC_ID_NSCODEC)
684         {
685                 nsc_context->width = surface_bits_command->width;
686                 nsc_context->height = surface_bits_command->height;
687                 nsc_process_message(nsc_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
688                 XSetFunction(xfi->display, xfi->gc, GXcopy);
689                 XSetFillStyle(xfi->display, xfi->gc, FillSolid);
690
691                 xfi->bmp_codec_nsc = (uint8*) xrealloc(xfi->bmp_codec_nsc,
692                                 surface_bits_command->width * surface_bits_command->height * 4);
693
694                 freerdp_image_flip(nsc_context->bmpdata, xfi->bmp_codec_nsc,
695                                 surface_bits_command->width, surface_bits_command->height, 32);
696
697                 image = XCreateImage(xfi->display, xfi->visual, 24, ZPixmap, 0,
698                         (char*) xfi->bmp_codec_nsc, surface_bits_command->width, surface_bits_command->height, 32, 0);
699
700                 XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0,
701                                 surface_bits_command->destLeft, surface_bits_command->destTop,
702                                 surface_bits_command->width, surface_bits_command->height);
703
704                 if (xfi->remote_app != true)
705                 {
706                         XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc,
707                                 surface_bits_command->destLeft, surface_bits_command->destTop,
708                                 surface_bits_command->width, surface_bits_command->height,
709                                 surface_bits_command->destLeft, surface_bits_command->destTop);
710                 }
711
712                 gdi_InvalidateRegion(xfi->hdc, surface_bits_command->destLeft, surface_bits_command->destTop,
713                                 surface_bits_command->width, surface_bits_command->height);
714
715                 XSetClipMask(xfi->display, xfi->gc, None);
716                 nsc_context_destroy(nsc_context);
717         }
718         else if (surface_bits_command->codecID == CODEC_ID_NONE)
719         {
720                 XSetFunction(xfi->display, xfi->gc, GXcopy);
721                 XSetFillStyle(xfi->display, xfi->gc, FillSolid);
722
723                 xfi->bmp_codec_none = (uint8*) xrealloc(xfi->bmp_codec_none,
724                                 surface_bits_command->width * surface_bits_command->height * 4);
725
726                 freerdp_image_flip(surface_bits_command->bitmapData, xfi->bmp_codec_none,
727                                 surface_bits_command->width, surface_bits_command->height, 32);
728
729                 image = XCreateImage(xfi->display, xfi->visual, 24, ZPixmap, 0,
730                         (char*) xfi->bmp_codec_none, surface_bits_command->width, surface_bits_command->height, 32, 0);
731
732                 XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0,
733                                 surface_bits_command->destLeft, surface_bits_command->destTop,
734                                 surface_bits_command->width, surface_bits_command->height);
735
736                 if (xfi->remote_app != true)
737                 {
738                         XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc,
739                                 surface_bits_command->destLeft, surface_bits_command->destTop,
740                                 surface_bits_command->width, surface_bits_command->height,
741                                 surface_bits_command->destLeft, surface_bits_command->destTop);
742                 }
743
744                 gdi_InvalidateRegion(xfi->hdc, surface_bits_command->destLeft, surface_bits_command->destTop,
745                                 surface_bits_command->width, surface_bits_command->height);
746
747                 XSetClipMask(xfi->display, xfi->gc, None);
748         }
749         else
750         {
751                 printf("Unsupported codecID %d\n", surface_bits_command->codecID);
752         }
753 }
754
755 void xf_gdi_register_update_callbacks(rdpUpdate* update)
756 {
757         rdpPrimaryUpdate* primary = update->primary;
758
759         update->Palette = xf_gdi_palette_update;
760         update->SetBounds = xf_gdi_set_bounds;
761
762         primary->DstBlt = xf_gdi_dstblt;
763         primary->PatBlt = xf_gdi_patblt;
764         primary->ScrBlt = xf_gdi_scrblt;
765         primary->OpaqueRect = xf_gdi_opaque_rect;
766         primary->DrawNineGrid = NULL;
767         primary->MultiDstBlt = NULL;
768         primary->MultiPatBlt = NULL;
769         primary->MultiScrBlt = NULL;
770         primary->MultiOpaqueRect = xf_gdi_multi_opaque_rect;
771         primary->MultiDrawNineGrid = NULL;
772         primary->LineTo = xf_gdi_line_to;
773         primary->Polyline = xf_gdi_polyline;
774         primary->MemBlt = xf_gdi_memblt;
775         primary->Mem3Blt = xf_gdi_mem3blt;
776         primary->SaveBitmap = NULL;
777         primary->GlyphIndex = NULL;
778         primary->FastIndex = NULL;
779         primary->FastGlyph = NULL;
780         primary->PolygonSC = NULL;
781         primary->PolygonCB = NULL;
782         primary->EllipseSC = NULL;
783         primary->EllipseCB = NULL;
784
785         update->SurfaceBits = xf_gdi_surface_bits;
786         update->SurfaceFrameMarker = xf_gdi_surface_frame_marker;
787 }
788