Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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 <olv@lunarg.com>
  26.  */
  27.  
  28. #include <windows.h>
  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. }
  428.