uploaded original spice-server-0.12.4 and celt-0.5.1.3
[sdk/emulator/libs/spice-server.git] / client / windows / red_drawable.cpp
1 /*
2    Copyright (C) 2009 Red Hat, Inc.
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, see <http://www.gnu.org/licenses/>.
16 */
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20
21 #include "common.h"
22 #include "red_drawable.h"
23 #include "pixels_source_p.h"
24 #include "utils.h"
25 #include "threads.h"
26
27 static const uint64_t lock_timout = 1000 * 1000 * 10; /*10ms*/
28
29 void RedDrawable::copy_pixels(const PixelsSource& src, int src_x, int src_y, const SpiceRect& dest)
30 {
31     PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
32     PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque();
33
34     for (;;) {
35         Lock lock(*dest_p_data->_mutex);
36         Lock timed_lock(*src_p_data->_mutex, lock_timout);
37         if (!timed_lock.is_locked()) {
38             continue;
39         }
40         BitBlt(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y,
41                dest.right - dest.left, dest.bottom - dest.top,
42                src_p_data->dc, src_x + src._origin.x,
43                src_y + src._origin.y, SRCCOPY);
44         return;
45     }
46 }
47
48 void RedDrawable::blend_pixels(const PixelsSource& src, int src_x, int src_y, const SpiceRect& dest)
49 {
50     static BLENDFUNCTION blend_func = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA};
51
52     int width = dest.right - dest.left;
53     int height = dest.bottom - dest.top;
54     PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
55     PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque();
56     for (;;) {
57         RecurciveLock lock(*dest_p_data->_mutex);
58         RecurciveLock timed_lock(*src_p_data->_mutex, lock_timout);
59         if (!timed_lock.is_locked()) {
60             continue;
61         }
62         AlphaBlend(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y, width, height,
63                    src_p_data->dc, src_x + src._origin.x, src_y + src._origin.y, width, height,
64                    blend_func);
65         return;
66     }
67 }
68
69 void RedDrawable::combine_pixels(const PixelsSource& src, int src_x, int src_y, const SpiceRect& dest,
70                                  CombineOP op)
71 {
72     DWORD rop;
73     switch (op) {
74     case OP_COPY:
75         rop = SRCCOPY;
76         break;
77     case OP_AND:
78         rop = SRCAND;
79         break;
80     case OP_XOR:
81         rop = SRCINVERT;
82         break;
83     default:
84         THROW("invalid op %d", op);
85     }
86
87     PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
88     PixelsSource_p* src_p_data = (PixelsSource_p*)src.get_opaque();
89     for (;;) {
90         RecurciveLock lock(*dest_p_data->_mutex);
91         RecurciveLock timed_lock(*src_p_data->_mutex, lock_timout);
92         if (!timed_lock.is_locked()) {
93             continue;
94         }
95         BitBlt(dest_p_data->dc, dest.left + _origin.x, dest.top + _origin.y,
96                dest.right - dest.left, dest.bottom - dest.top,
97                src_p_data->dc, src_x + src._origin.x,
98                src_y + src._origin.y, rop);
99         return;
100     }
101 }
102
103 void RedDrawable::erase_rect(const SpiceRect& rect, rgb32_t color)
104 {
105     RECT r;
106     r.left = rect.left + _origin.x;
107     r.right = rect.right + _origin.x;
108     r.top = rect.top + _origin.y;
109     r.bottom = rect.bottom + _origin.y;
110
111     PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
112     RecurciveLock lock(*dest_p_data->_mutex);
113     FillRect(dest_p_data->dc, &r, (HBRUSH)GetStockObject(BLACK_BRUSH));
114 }
115
116 void RedDrawable::fill_rect(const SpiceRect& rect, rgb32_t color)
117 {
118     RECT r;
119     r.left = rect.left + _origin.x;
120     r.right = rect.right + _origin.x;
121     r.top = rect.top + _origin.y;
122     r.bottom = rect.bottom + _origin.y;
123
124     HBRUSH brush = CreateSolidBrush(RGB(rgb32_get_red(color),
125                                         rgb32_get_green(color),
126                                         rgb32_get_blue(color)));
127     for (;;) {
128         PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
129         RecurciveLock lock(*dest_p_data->_mutex);
130         FillRect(dest_p_data->dc, &r, brush);
131         break;
132     }
133     DeleteObject(brush);
134 }
135
136 void RedDrawable::frame_rect(const SpiceRect& rect, rgb32_t color)
137 {
138     RECT r;
139     r.left = rect.left + _origin.x;
140     r.right = rect.right + _origin.x;
141     r.top = rect.top + _origin.y;
142     r.bottom = rect.bottom + _origin.y;
143     HBRUSH brush = CreateSolidBrush(RGB(rgb32_get_red(color),
144                                         rgb32_get_green(color),
145                                         rgb32_get_blue(color)));
146     for (;;) {
147         PixelsSource_p* dest_p_data = (PixelsSource_p*)get_opaque();
148         RecurciveLock lock(*dest_p_data->_mutex);
149         FrameRect(dest_p_data->dc, &r, brush);
150         break;
151     }
152     DeleteObject(brush);
153 }