Subversion Repositories Kolibri OS

Rev

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
}