uploaded original spice-server-0.12.4 and celt-0.5.1.3
[sdk/emulator/libs/spice-server.git] / client / windows / red_pixmap_gdi.cpp
1 /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3    Copyright (C) 2009 Red Hat, Inc.
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include "common.h"
23 #include "red_pixmap_gdi.h"
24 #include "red_pixmap.h"
25 #include "debug.h"
26 #include "utils.h"
27 #include "pixels_source_p.h"
28 #include "platform_utils.h"
29
30 struct RedPixmap_p {
31     PixelsSource_p pixels_source_p;
32     HBITMAP prev_bitmap;
33 };
34
35 RedPixmapGdi::RedPixmapGdi(int width, int height, RedDrawable::Format format, bool top_bottom)
36     : RedPixmap(width, height, format, top_bottom)
37 {
38     DWORD *pixel_format;
39     ASSERT(format == RedDrawable::ARGB32 || format == RedDrawable::RGB32
40            || format == RedDrawable::RGB16_555 || format == RedDrawable::RGB16_565
41            || format == RedDrawable::A1);
42     ASSERT(sizeof(RedPixmap_p) <= PIXELES_SOURCE_OPAQUE_SIZE);
43
44     struct {
45         BITMAPINFO inf;
46         RGBQUAD palette[255];
47     } bitmap_info;
48
49     memset(&bitmap_info, 0, sizeof(bitmap_info));
50     bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader);
51     bitmap_info.inf.bmiHeader.biWidth = _width;
52     bitmap_info.inf.bmiHeader.biHeight = top_bottom ? -_height : _height;
53
54     bitmap_info.inf.bmiHeader.biPlanes = 1;
55     bitmap_info.inf.bmiHeader.biBitCount = RedDrawable::format_to_bpp(format);
56     if (format == RedDrawable::RGB16_565) {
57         bitmap_info.inf.bmiHeader.biCompression = BI_BITFIELDS;
58
59     } else {
60         bitmap_info.inf.bmiHeader.biCompression = BI_RGB;
61     }
62     switch (format) {
63     case RedDrawable::A1:
64         bitmap_info.inf.bmiColors[0].rgbRed = 0;
65         bitmap_info.inf.bmiColors[0].rgbGreen = 0;
66         bitmap_info.inf.bmiColors[0].rgbBlue = 0;
67 #ifndef __MINGW32__
68         // inf.bmiColors is [1] in mingw/include/wingdi.h
69         bitmap_info.inf.bmiColors[1].rgbRed = 0xff;
70         bitmap_info.inf.bmiColors[1].rgbGreen = 0xff;
71         bitmap_info.inf.bmiColors[1].rgbBlue = 0xff;
72 #endif
73         break;
74      case RedDrawable::RGB16_565:
75         pixel_format = (DWORD *)bitmap_info.inf.bmiColors;
76         pixel_format[0] = 0xf800;
77         pixel_format[1] = 0x07e0;
78         pixel_format[2] = 0x001f;
79         break;
80      case RedDrawable::ARGB32:
81      case RedDrawable::RGB32:
82      case RedDrawable::RGB16_555:
83         break;
84     }
85     AutoDC dc(create_compatible_dc());
86     AutoGDIObject bitmap(CreateDIBSection(dc.get(), &bitmap_info.inf, 0,
87                                           (VOID **)&_data, NULL, 0));
88     if (!bitmap.valid()) {
89         THROW("create compatible bitmap failed");
90     }
91     memset(_data, 1, 1);
92     ((RedPixmap_p*)get_opaque())->prev_bitmap = (HBITMAP)SelectObject(dc.get(), bitmap.release());
93     ((RedPixmap_p*)get_opaque())->pixels_source_p.dc = dc.release();
94 }
95
96 HDC RedPixmapGdi::get_dc()
97 {
98     return ((RedPixmap_p*)get_opaque())->pixels_source_p.dc;
99 }
100
101 void *RedPixmapGdi::get_memptr()
102 {
103     return _data;
104 }
105
106 RedPixmapGdi::~RedPixmapGdi()
107 {
108     HDC dc = ((RedPixmap_p*)get_opaque())->pixels_source_p.dc;
109     if (dc) {
110         HBITMAP prev_bitmap = ((RedPixmap_p*)get_opaque())->prev_bitmap;
111         HBITMAP bitmap = (HBITMAP)SelectObject(dc, prev_bitmap);
112         DeleteObject(bitmap);
113         DeleteDC(dc);
114     }
115 }
116
117 RecurciveMutex& RedPixmapGdi::get_mutex()
118 {
119     RedPixmap_p* p_data = (RedPixmap_p*)get_opaque();
120     return *p_data->pixels_source_p._mutex;
121 }