1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 *
27 **************************************************************************/
28
29 /**
30 * @file
31 * GDI software rasterizer support.
32 *
33 * @author Jose Fonseca <[email protected]>
34 */
35
36
37 #include <windows.h>
38
39 #include "util/format/u_formats.h"
40 #include "pipe/p_context.h"
41 #include "util/u_inlines.h"
42 #include "util/format/u_format.h"
43 #include "util/u_math.h"
44 #include "util/u_memory.h"
45 #include "frontend/sw_winsys.h"
46 #include "gdi_sw_winsys.h"
47 #include "wgl/stw_gdishim.h"
48
49
50 struct gdi_sw_displaytarget
51 {
52 enum pipe_format format;
53 unsigned width;
54 unsigned height;
55 unsigned stride;
56
57 unsigned size;
58
59 void *data;
60
61 BITMAPV5HEADER bmi;
62 };
63
64 struct gdi_sw_winsys {
65 struct sw_winsys base;
66
67 HDC (*acquire_hdc)(void *winsys_drawable_handle);
68 void (*release_hdc)(void *winsys_drawable_handle, HDC hdc);
69 };
70
71 /** Cast wrapper */
72 static inline struct gdi_sw_displaytarget *
gdi_sw_displaytarget(struct sw_displaytarget * buf)73 gdi_sw_displaytarget( struct sw_displaytarget *buf )
74 {
75 return (struct gdi_sw_displaytarget *)buf;
76 }
77
78
79 /** Cast wrapper */
80 static inline struct gdi_sw_winsys *
gdi_sw_winsys(struct sw_winsys * buf)81 gdi_sw_winsys( struct sw_winsys *buf )
82 {
83 return (struct gdi_sw_winsys *)buf;
84 }
85
86
87 static bool
gdi_sw_is_displaytarget_format_supported(struct sw_winsys * ws,unsigned tex_usage,enum pipe_format format)88 gdi_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
89 unsigned tex_usage,
90 enum pipe_format format )
91 {
92 switch(format) {
93 case PIPE_FORMAT_B8G8R8X8_UNORM:
94 case PIPE_FORMAT_B8G8R8A8_UNORM:
95 case PIPE_FORMAT_B5G6R5_UNORM:
96 case PIPE_FORMAT_B5G5R5A1_UNORM:
97 case PIPE_FORMAT_B4G4R4A4_UNORM:
98 case PIPE_FORMAT_R10G10B10A2_UNORM:
99 case PIPE_FORMAT_R8G8B8X8_UNORM:
100 case PIPE_FORMAT_R8G8B8A8_UNORM:
101 return true;
102
103 /* TODO: Support other formats possible with BMPs, as described in
104 * http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx */
105
106 default:
107 return false;
108 }
109 }
110
111
112 static void *
gdi_sw_displaytarget_map(struct sw_winsys * ws,struct sw_displaytarget * dt,unsigned flags)113 gdi_sw_displaytarget_map(struct sw_winsys *ws,
114 struct sw_displaytarget *dt,
115 unsigned flags )
116 {
117 struct gdi_sw_displaytarget *gdt = gdi_sw_displaytarget(dt);
118
119 return gdt->data;
120 }
121
122
123 static void
gdi_sw_displaytarget_unmap(struct sw_winsys * ws,struct sw_displaytarget * dt)124 gdi_sw_displaytarget_unmap(struct sw_winsys *ws,
125 struct sw_displaytarget *dt )
126 {
127
128 }
129
130
131 static void
gdi_sw_displaytarget_destroy(struct sw_winsys * winsys,struct sw_displaytarget * dt)132 gdi_sw_displaytarget_destroy(struct sw_winsys *winsys,
133 struct sw_displaytarget *dt)
134 {
135 struct gdi_sw_displaytarget *gdt = gdi_sw_displaytarget(dt);
136
137 align_free(gdt->data);
138 FREE(gdt);
139 }
140
141
142 static struct sw_displaytarget *
gdi_sw_displaytarget_create(struct sw_winsys * winsys,unsigned tex_usage,enum pipe_format format,unsigned width,unsigned height,unsigned alignment,const void * front_private,unsigned * stride)143 gdi_sw_displaytarget_create(struct sw_winsys *winsys,
144 unsigned tex_usage,
145 enum pipe_format format,
146 unsigned width, unsigned height,
147 unsigned alignment,
148 const void *front_private,
149 unsigned *stride)
150 {
151 struct gdi_sw_displaytarget *gdt;
152 unsigned cpp;
153 unsigned bpp;
154
155 gdt = CALLOC_STRUCT(gdi_sw_displaytarget);
156 if(!gdt)
157 goto no_gdt;
158
159 gdt->format = format;
160 gdt->width = width;
161 gdt->height = height;
162
163 bpp = util_format_get_blocksizebits(format);
164 cpp = util_format_get_blocksize(format);
165
166 gdt->stride = align(width * cpp, alignment);
167 gdt->size = gdt->stride * height;
168
169 gdt->data = align_malloc(gdt->size, alignment);
170 if(!gdt->data)
171 goto no_data;
172
173 gdt->bmi.bV5Size = sizeof(BITMAPV5HEADER);
174 gdt->bmi.bV5Width = gdt->stride / cpp;
175 gdt->bmi.bV5Height = -(long)height;
176 gdt->bmi.bV5Planes = 1;
177 gdt->bmi.bV5BitCount = bpp;
178 gdt->bmi.bV5Compression = BI_RGB;
179 gdt->bmi.bV5SizeImage = 0;
180 gdt->bmi.bV5XPelsPerMeter = 0;
181 gdt->bmi.bV5YPelsPerMeter = 0;
182 gdt->bmi.bV5ClrUsed = 0;
183 gdt->bmi.bV5ClrImportant = 0;
184
185 if (format == PIPE_FORMAT_B5G6R5_UNORM) {
186 gdt->bmi.bV5Compression = BI_BITFIELDS;
187 gdt->bmi.bV5RedMask = 0xF800;
188 gdt->bmi.bV5GreenMask = 0x07E0;
189 gdt->bmi.bV5BlueMask = 0x001F;
190 } else if (format == PIPE_FORMAT_B4G4R4A4_UNORM) {
191 gdt->bmi.bV5Compression = BI_BITFIELDS;
192 gdt->bmi.bV5RedMask = 0x0F00;
193 gdt->bmi.bV5GreenMask = 0x00F0;
194 gdt->bmi.bV5BlueMask = 0x000F;
195 } else if (format == PIPE_FORMAT_R10G10B10A2_UNORM) {
196 gdt->bmi.bV5Compression = BI_BITFIELDS;
197 gdt->bmi.bV5RedMask = 0x000003FF;
198 gdt->bmi.bV5GreenMask = 0x000FFC00;
199 gdt->bmi.bV5BlueMask = 0x3FF00000;
200 } else if (format == PIPE_FORMAT_R8G8B8X8_UNORM || format == PIPE_FORMAT_R8G8B8A8_UNORM) {
201 gdt->bmi.bV5Compression = BI_BITFIELDS;
202 gdt->bmi.bV5RedMask = 0x0000ff;
203 gdt->bmi.bV5GreenMask = 0x00ff00;
204 gdt->bmi.bV5BlueMask = 0xff0000;
205 }
206
207 *stride = gdt->stride;
208 return (struct sw_displaytarget *)gdt;
209
210 no_data:
211 FREE(gdt);
212 no_gdt:
213 return NULL;
214 }
215
216
217 static struct sw_displaytarget *
gdi_sw_displaytarget_from_handle(struct sw_winsys * winsys,const struct pipe_resource * templet,struct winsys_handle * whandle,unsigned * stride)218 gdi_sw_displaytarget_from_handle(struct sw_winsys *winsys,
219 const struct pipe_resource *templet,
220 struct winsys_handle *whandle,
221 unsigned *stride)
222 {
223 assert(0);
224 return NULL;
225 }
226
227
228 static bool
gdi_sw_displaytarget_get_handle(struct sw_winsys * winsys,struct sw_displaytarget * dt,struct winsys_handle * whandle)229 gdi_sw_displaytarget_get_handle(struct sw_winsys *winsys,
230 struct sw_displaytarget *dt,
231 struct winsys_handle *whandle)
232 {
233 assert(0);
234 return false;
235 }
236
237
238 void
gdi_sw_display(struct sw_winsys * winsys,struct sw_displaytarget * dt,HDC hDC)239 gdi_sw_display( struct sw_winsys *winsys,
240 struct sw_displaytarget *dt,
241 HDC hDC )
242 {
243 struct gdi_sw_displaytarget *gdt = gdi_sw_displaytarget(dt);
244
245 StretchDIBits(hDC,
246 0, 0, gdt->width, gdt->height,
247 0, 0, gdt->width, gdt->height,
248 gdt->data, (BITMAPINFO *)&gdt->bmi, 0, SRCCOPY);
249 }
250
251 static void
gdi_sw_displaytarget_display(struct sw_winsys * _winsys,struct sw_displaytarget * dt,void * context_private,unsigned nboxes,struct pipe_box * box)252 gdi_sw_displaytarget_display(struct sw_winsys *_winsys,
253 struct sw_displaytarget *dt,
254 void *context_private,
255 unsigned nboxes,
256 struct pipe_box *box)
257 {
258 struct gdi_sw_winsys *winsys = gdi_sw_winsys(_winsys);
259 HDC hDC = winsys->acquire_hdc(context_private);
260
261 gdi_sw_display(_winsys, dt, hDC);
262 winsys->release_hdc(context_private, hDC);
263 }
264
265
266 static void
gdi_sw_destroy(struct sw_winsys * winsys)267 gdi_sw_destroy(struct sw_winsys *winsys)
268 {
269 FREE(winsys);
270 }
271
272 struct sw_winsys *
gdi_create_sw_winsys(HDC (* acquire_hdc)(void * winsys_drawable_handle),void (* release_hdc)(void * winsys_drawable_handle,HDC hdc))273 gdi_create_sw_winsys(
274 HDC (*acquire_hdc)(void *winsys_drawable_handle),
275 void (*release_hdc)(void *winsys_drawable_handle, HDC hdc))
276 {
277 static struct gdi_sw_winsys *winsys;
278
279 winsys = CALLOC_STRUCT(gdi_sw_winsys);
280 if(!winsys)
281 return NULL;
282
283 winsys->acquire_hdc = acquire_hdc;
284 winsys->release_hdc = release_hdc;
285
286 winsys->base.destroy = gdi_sw_destroy;
287 winsys->base.is_displaytarget_format_supported = gdi_sw_is_displaytarget_format_supported;
288 winsys->base.displaytarget_create = gdi_sw_displaytarget_create;
289 winsys->base.displaytarget_from_handle = gdi_sw_displaytarget_from_handle;
290 winsys->base.displaytarget_get_handle = gdi_sw_displaytarget_get_handle;
291 winsys->base.displaytarget_map = gdi_sw_displaytarget_map;
292 winsys->base.displaytarget_unmap = gdi_sw_displaytarget_unmap;
293 winsys->base.displaytarget_display = gdi_sw_displaytarget_display;
294 winsys->base.displaytarget_destroy = gdi_sw_displaytarget_destroy;
295
296 return &winsys->base;
297 }
298
299
gdi_sw_acquire_hdc_by_value(void * context_private)300 HDC gdi_sw_acquire_hdc_by_value(void *context_private) {
301 return (HDC)context_private;
302 };
303
gdi_sw_release_hdc_by_value(void * context_private,HDC hdc)304 void gdi_sw_release_hdc_by_value(void *context_private, HDC hdc) {
305 // Nothing to do
306 };
307