Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 2010 LunarG Inc. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
22 | * DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Chia-I Wu |
||
26 | */ |
||
27 | |||
28 | #include |
||
29 | |||
30 | #include "pipe/p_compiler.h" |
||
31 | #include "util/u_memory.h" |
||
32 | #include "util/u_format.h" |
||
33 | #include "util/u_inlines.h" |
||
34 | #include "gdi/gdi_sw_winsys.h" |
||
35 | |||
36 | #include "common/native_helper.h" |
||
37 | #include "common/native.h" |
||
38 | |||
39 | struct gdi_display { |
||
40 | struct native_display base; |
||
41 | |||
42 | HDC hDC; |
||
43 | const struct native_event_handler *event_handler; |
||
44 | |||
45 | struct native_config *configs; |
||
46 | int num_configs; |
||
47 | }; |
||
48 | |||
49 | struct gdi_surface { |
||
50 | struct native_surface base; |
||
51 | |||
52 | HWND hWnd; |
||
53 | enum pipe_format color_format; |
||
54 | |||
55 | struct gdi_display *gdpy; |
||
56 | |||
57 | unsigned int server_stamp; |
||
58 | unsigned int client_stamp; |
||
59 | |||
60 | struct resource_surface *rsurf; |
||
61 | }; |
||
62 | |||
63 | static INLINE struct gdi_display * |
||
64 | gdi_display(const struct native_display *ndpy) |
||
65 | { |
||
66 | return (struct gdi_display *) ndpy; |
||
67 | } |
||
68 | |||
69 | static INLINE struct gdi_surface * |
||
70 | gdi_surface(const struct native_surface *nsurf) |
||
71 | { |
||
72 | return (struct gdi_surface *) nsurf; |
||
73 | } |
||
74 | |||
75 | /** |
||
76 | * Update the geometry of the surface. This is a slow functions. |
||
77 | */ |
||
78 | static void |
||
79 | gdi_surface_update_geometry(struct native_surface *nsurf) |
||
80 | { |
||
81 | struct gdi_surface *gsurf = gdi_surface(nsurf); |
||
82 | RECT rect; |
||
83 | uint w, h; |
||
84 | |||
85 | GetClientRect(gsurf->hWnd, &rect); |
||
86 | w = rect.right - rect.left; |
||
87 | h = rect.bottom - rect.top; |
||
88 | |||
89 | if (resource_surface_set_size(gsurf->rsurf, w, h)) |
||
90 | gsurf->server_stamp++; |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * Update the buffers of the surface. |
||
95 | */ |
||
96 | static boolean |
||
97 | gdi_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) |
||
98 | { |
||
99 | struct gdi_surface *gsurf = gdi_surface(nsurf); |
||
100 | |||
101 | if (gsurf->client_stamp != gsurf->server_stamp) { |
||
102 | gdi_surface_update_geometry(&gsurf->base); |
||
103 | gsurf->client_stamp = gsurf->server_stamp; |
||
104 | } |
||
105 | |||
106 | return resource_surface_add_resources(gsurf->rsurf, buffer_mask); |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * Emulate an invalidate event. |
||
111 | */ |
||
112 | static void |
||
113 | gdi_surface_invalidate(struct native_surface *nsurf) |
||
114 | { |
||
115 | struct gdi_surface *gsurf = gdi_surface(nsurf); |
||
116 | struct gdi_display *gdpy = gsurf->gdpy; |
||
117 | |||
118 | gsurf->server_stamp++; |
||
119 | gdpy->event_handler->invalid_surface(&gdpy->base, |
||
120 | &gsurf->base, gsurf->server_stamp); |
||
121 | } |
||
122 | |||
123 | static boolean |
||
124 | gdi_surface_flush_frontbuffer(struct native_surface *nsurf) |
||
125 | { |
||
126 | struct gdi_surface *gsurf = gdi_surface(nsurf); |
||
127 | HDC hDC; |
||
128 | boolean ret; |
||
129 | |||
130 | hDC = GetDC(gsurf->hWnd); |
||
131 | ret = resource_surface_present(gsurf->rsurf, |
||
132 | NATIVE_ATTACHMENT_FRONT_LEFT, (void *) hDC); |
||
133 | ReleaseDC(gsurf->hWnd, hDC); |
||
134 | |||
135 | /* force buffers to be updated in next validation call */ |
||
136 | gdi_surface_invalidate(&gsurf->base); |
||
137 | |||
138 | return ret; |
||
139 | } |
||
140 | |||
141 | static boolean |
||
142 | gdi_surface_swap_buffers(struct native_surface *nsurf) |
||
143 | { |
||
144 | struct gdi_surface *gsurf = gdi_surface(nsurf); |
||
145 | HDC hDC; |
||
146 | boolean ret; |
||
147 | |||
148 | hDC = GetDC(gsurf->hWnd); |
||
149 | ret = resource_surface_present(gsurf->rsurf, |
||
150 | NATIVE_ATTACHMENT_BACK_LEFT, (void *) hDC); |
||
151 | ReleaseDC(gsurf->hWnd, hDC); |
||
152 | |||
153 | resource_surface_swap_buffers(gsurf->rsurf, |
||
154 | NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE); |
||
155 | /* the front/back buffers have been swapped */ |
||
156 | gdi_surface_invalidate(&gsurf->base); |
||
157 | |||
158 | return ret; |
||
159 | } |
||
160 | |||
161 | static boolean |
||
162 | gdi_surface_present(struct native_surface *nsurf, |
||
163 | const struct native_present_control *ctrl) |
||
164 | { |
||
165 | boolean ret; |
||
166 | |||
167 | if (ctrl->preserve || ctrl->swap_interval) |
||
168 | return FALSE; |
||
169 | |||
170 | switch (ctrl->natt) { |
||
171 | case NATIVE_ATTACHMENT_FRONT_LEFT: |
||
172 | ret = gdi_surface_flush_frontbuffer(nsurf); |
||
173 | break; |
||
174 | case NATIVE_ATTACHMENT_BACK_LEFT: |
||
175 | ret = gdi_surface_swap_buffers(nsurf); |
||
176 | break; |
||
177 | default: |
||
178 | ret = FALSE; |
||
179 | break; |
||
180 | } |
||
181 | |||
182 | return ret; |
||
183 | } |
||
184 | |||
185 | static boolean |
||
186 | gdi_surface_validate(struct native_surface *nsurf, uint attachment_mask, |
||
187 | unsigned int *seq_num, struct pipe_resource **textures, |
||
188 | int *width, int *height) |
||
189 | { |
||
190 | struct gdi_surface *gsurf = gdi_surface(nsurf); |
||
191 | uint w, h; |
||
192 | |||
193 | if (!gdi_surface_update_buffers(&gsurf->base, attachment_mask)) |
||
194 | return FALSE; |
||
195 | |||
196 | if (seq_num) |
||
197 | *seq_num = gsurf->client_stamp; |
||
198 | |||
199 | if (textures) |
||
200 | resource_surface_get_resources(gsurf->rsurf, textures, attachment_mask); |
||
201 | |||
202 | resource_surface_get_size(gsurf->rsurf, &w, &h); |
||
203 | if (width) |
||
204 | *width = w; |
||
205 | if (height) |
||
206 | *height = h; |
||
207 | |||
208 | return TRUE; |
||
209 | } |
||
210 | |||
211 | static void |
||
212 | gdi_surface_wait(struct native_surface *nsurf) |
||
213 | { |
||
214 | /* no-op */ |
||
215 | } |
||
216 | |||
217 | static void |
||
218 | gdi_surface_destroy(struct native_surface *nsurf) |
||
219 | { |
||
220 | struct gdi_surface *gsurf = gdi_surface(nsurf); |
||
221 | |||
222 | resource_surface_destroy(gsurf->rsurf); |
||
223 | FREE(gsurf); |
||
224 | } |
||
225 | |||
226 | static struct native_surface * |
||
227 | gdi_display_create_window_surface(struct native_display *ndpy, |
||
228 | EGLNativeWindowType win, |
||
229 | const struct native_config *nconf) |
||
230 | { |
||
231 | struct gdi_display *gdpy = gdi_display(ndpy); |
||
232 | struct gdi_surface *gsurf; |
||
233 | |||
234 | gsurf = CALLOC_STRUCT(gdi_surface); |
||
235 | if (!gsurf) |
||
236 | return NULL; |
||
237 | |||
238 | gsurf->gdpy = gdpy; |
||
239 | gsurf->color_format = nconf->color_format; |
||
240 | gsurf->hWnd = (HWND) win; |
||
241 | |||
242 | gsurf->rsurf = resource_surface_create(gdpy->base.screen, |
||
243 | gsurf->color_format, |
||
244 | PIPE_BIND_RENDER_TARGET | |
||
245 | PIPE_BIND_SAMPLER_VIEW | |
||
246 | PIPE_BIND_DISPLAY_TARGET | |
||
247 | PIPE_BIND_SCANOUT); |
||
248 | if (!gsurf->rsurf) { |
||
249 | FREE(gsurf); |
||
250 | return NULL; |
||
251 | } |
||
252 | |||
253 | /* initialize the geometry */ |
||
254 | gdi_surface_update_geometry(&gsurf->base); |
||
255 | |||
256 | gsurf->base.destroy = gdi_surface_destroy; |
||
257 | gsurf->base.present = gdi_surface_present; |
||
258 | gsurf->base.validate = gdi_surface_validate; |
||
259 | gsurf->base.wait = gdi_surface_wait; |
||
260 | |||
261 | return &gsurf->base; |
||
262 | } |
||
263 | |||
264 | static int |
||
265 | fill_color_formats(struct native_display *ndpy, enum pipe_format formats[8]) |
||
266 | { |
||
267 | struct pipe_screen *screen = ndpy->screen; |
||
268 | int i, count = 0; |
||
269 | |||
270 | enum pipe_format candidates[] = { |
||
271 | /* 32-bit */ |
||
272 | PIPE_FORMAT_B8G8R8A8_UNORM, |
||
273 | PIPE_FORMAT_A8R8G8B8_UNORM, |
||
274 | /* 24-bit */ |
||
275 | PIPE_FORMAT_B8G8R8X8_UNORM, |
||
276 | PIPE_FORMAT_X8R8G8B8_UNORM, |
||
277 | /* 16-bit */ |
||
278 | PIPE_FORMAT_B5G6R5_UNORM |
||
279 | }; |
||
280 | |||
281 | assert(Elements(candidates) <= 8); |
||
282 | |||
283 | for (i = 0; i < Elements(candidates); i++) { |
||
284 | if (screen->is_format_supported(screen, candidates[i], |
||
285 | PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) |
||
286 | formats[count++] = candidates[i]; |
||
287 | } |
||
288 | |||
289 | return count; |
||
290 | } |
||
291 | |||
292 | static const struct native_config ** |
||
293 | gdi_display_get_configs(struct native_display *ndpy, int *num_configs) |
||
294 | { |
||
295 | struct gdi_display *gdpy = gdi_display(ndpy); |
||
296 | const struct native_config **configs; |
||
297 | int i; |
||
298 | |||
299 | /* first time */ |
||
300 | if (!gdpy->configs) { |
||
301 | enum pipe_format formats[8]; |
||
302 | int i, count; |
||
303 | |||
304 | count = fill_color_formats(&gdpy->base, formats); |
||
305 | |||
306 | gdpy->configs = CALLOC(count, sizeof(*gdpy->configs)); |
||
307 | if (!gdpy->configs) |
||
308 | return NULL; |
||
309 | |||
310 | for (i = 0; i < count; i++) { |
||
311 | struct native_config *nconf = &gdpy->configs[i]; |
||
312 | |||
313 | nconf->buffer_mask = |
||
314 | (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | |
||
315 | (1 << NATIVE_ATTACHMENT_BACK_LEFT); |
||
316 | nconf->color_format = formats[i]; |
||
317 | |||
318 | nconf->window_bit = TRUE; |
||
319 | } |
||
320 | |||
321 | gdpy->num_configs = count; |
||
322 | } |
||
323 | |||
324 | configs = MALLOC(gdpy->num_configs * sizeof(*configs)); |
||
325 | if (configs) { |
||
326 | for (i = 0; i < gdpy->num_configs; i++) |
||
327 | configs[i] = (const struct native_config *) &gdpy->configs[i]; |
||
328 | if (num_configs) |
||
329 | *num_configs = gdpy->num_configs; |
||
330 | } |
||
331 | return configs; |
||
332 | } |
||
333 | |||
334 | static int |
||
335 | gdi_display_get_param(struct native_display *ndpy, |
||
336 | enum native_param_type param) |
||
337 | { |
||
338 | int val; |
||
339 | |||
340 | switch (param) { |
||
341 | case NATIVE_PARAM_USE_NATIVE_BUFFER: |
||
342 | /* private buffers are allocated */ |
||
343 | val = FALSE; |
||
344 | break; |
||
345 | case NATIVE_PARAM_PRESERVE_BUFFER: |
||
346 | case NATIVE_PARAM_MAX_SWAP_INTERVAL: |
||
347 | default: |
||
348 | val = 0; |
||
349 | break; |
||
350 | } |
||
351 | |||
352 | return val; |
||
353 | } |
||
354 | |||
355 | static void |
||
356 | gdi_display_destroy(struct native_display *ndpy) |
||
357 | { |
||
358 | struct gdi_display *gdpy = gdi_display(ndpy); |
||
359 | |||
360 | FREE(gdpy->configs); |
||
361 | |||
362 | ndpy_uninit(ndpy); |
||
363 | |||
364 | FREE(gdpy); |
||
365 | } |
||
366 | |||
367 | static boolean |
||
368 | gdi_display_init_screen(struct native_display *ndpy) |
||
369 | { |
||
370 | struct gdi_display *gdpy = gdi_display(ndpy); |
||
371 | struct sw_winsys *winsys; |
||
372 | |||
373 | winsys = gdi_create_sw_winsys(); |
||
374 | if (!winsys) |
||
375 | return FALSE; |
||
376 | |||
377 | gdpy->base.screen = gdpy->event_handler->new_sw_screen(&gdpy->base, winsys); |
||
378 | if (!gdpy->base.screen) { |
||
379 | if (winsys->destroy) |
||
380 | winsys->destroy(winsys); |
||
381 | return FALSE; |
||
382 | } |
||
383 | |||
384 | return TRUE; |
||
385 | } |
||
386 | |||
387 | static struct native_display * |
||
388 | gdi_create_display(HDC hDC, const struct native_event_handler *event_handler) |
||
389 | { |
||
390 | struct gdi_display *gdpy; |
||
391 | |||
392 | gdpy = CALLOC_STRUCT(gdi_display); |
||
393 | if (!gdpy) |
||
394 | return NULL; |
||
395 | |||
396 | gdpy->hDC = hDC; |
||
397 | gdpy->event_handler = event_handler; |
||
398 | |||
399 | gdpy->base.init_screen = gdi_display_init_screen; |
||
400 | gdpy->base.destroy = gdi_display_destroy; |
||
401 | gdpy->base.get_param = gdi_display_get_param; |
||
402 | |||
403 | gdpy->base.get_configs = gdi_display_get_configs; |
||
404 | gdpy->base.create_window_surface = gdi_display_create_window_surface; |
||
405 | |||
406 | return &gdpy->base; |
||
407 | } |
||
408 | |||
409 | static const struct native_event_handler *gdi_event_handler; |
||
410 | |||
411 | static struct native_display * |
||
412 | native_create_display(void *dpy, boolean use_sw) |
||
413 | { |
||
414 | return gdi_create_display((HDC) dpy, gdi_event_handler); |
||
415 | } |
||
416 | |||
417 | static const struct native_platform gdi_platform = { |
||
418 | "GDI", /* name */ |
||
419 | native_create_display |
||
420 | }; |
||
421 | |||
422 | const struct native_platform * |
||
423 | native_get_gdi_platform(const struct native_event_handler *event_handler) |
||
424 | { |
||
425 | gdi_event_handler = event_handler; |
||
426 | return &gdi_platform; |
||
427 | }>><>><>>>=> |