Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2010 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 above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include <windows.h>
  29.  
  30. #define WGL_WGLEXT_PROTOTYPES
  31.  
  32. #include <GL/gl.h>
  33. #include <GL/wglext.h>
  34.  
  35. #include "pipe/p_defines.h"
  36. #include "pipe/p_screen.h"
  37.  
  38. #include "stw_device.h"
  39. #include "stw_pixelformat.h"
  40. #include "stw_framebuffer.h"
  41.  
  42.  
  43. #define LARGE_WINDOW_SIZE 60000
  44.  
  45.  
  46. static LRESULT CALLBACK
  47. WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  48. {
  49.     MINMAXINFO *pMMI;
  50.     switch (uMsg) {
  51.     case WM_GETMINMAXINFO:
  52.         // Allow to create a window bigger than the desktop
  53.         pMMI = (MINMAXINFO *)lParam;
  54.         pMMI->ptMaxSize.x = LARGE_WINDOW_SIZE;
  55.         pMMI->ptMaxSize.y = LARGE_WINDOW_SIZE;
  56.         pMMI->ptMaxTrackSize.x = LARGE_WINDOW_SIZE;
  57.         pMMI->ptMaxTrackSize.y = LARGE_WINDOW_SIZE;
  58.         break;
  59.     default:
  60.         break;
  61.     }
  62.  
  63.     return DefWindowProc(hWnd, uMsg, wParam, lParam);
  64. }
  65.  
  66.  
  67. HPBUFFERARB WINAPI
  68. wglCreatePbufferARB(HDC hCurrentDC,
  69.                     int iPixelFormat,
  70.                     int iWidth,
  71.                     int iHeight,
  72.                     const int *piAttribList)
  73. {
  74.    static boolean first = TRUE;
  75.    const int *piAttrib;
  76.    int useLargest = 0;
  77.    const struct stw_pixelformat_info *info;
  78.    struct stw_framebuffer *fb;
  79.    DWORD dwExStyle;
  80.    DWORD dwStyle;
  81.    RECT rect;
  82.    HWND hWnd;
  83.    HDC hDC;
  84.    int iDisplayablePixelFormat;
  85.    PIXELFORMATDESCRIPTOR pfd;
  86.    BOOL bRet;
  87.  
  88.    info = stw_pixelformat_get_info(iPixelFormat - 1);
  89.    if (!info) {
  90.       SetLastError(ERROR_INVALID_PIXEL_FORMAT);
  91.       return 0;
  92.    }
  93.  
  94.    if (iWidth <= 0 || iHeight <= 0) {
  95.       SetLastError(ERROR_INVALID_DATA);
  96.       return 0;
  97.    }
  98.  
  99.    for (piAttrib = piAttribList; *piAttrib; piAttrib++) {
  100.       switch (*piAttrib) {
  101.       case WGL_PBUFFER_LARGEST_ARB:
  102.          piAttrib++;
  103.          useLargest = *piAttrib;
  104.          break;
  105.       default:
  106.          SetLastError(ERROR_INVALID_DATA);
  107.          return 0;
  108.       }
  109.    }
  110.  
  111.    if (iWidth > stw_dev->max_2d_length) {
  112.       if (useLargest) {
  113.          iWidth = stw_dev->max_2d_length;
  114.       } else {
  115.          SetLastError(ERROR_NO_SYSTEM_RESOURCES);
  116.          return 0;
  117.       }
  118.    }
  119.  
  120.    if (iHeight > stw_dev->max_2d_length) {
  121.       if (useLargest) {
  122.          iHeight = stw_dev->max_2d_length;
  123.       } else {
  124.          SetLastError(ERROR_NO_SYSTEM_RESOURCES);
  125.          return 0;
  126.       }
  127.    }
  128.  
  129.    /*
  130.     * Implement pbuffers through invisible windows
  131.     */
  132.  
  133.    if (first) {
  134.       WNDCLASS wc;
  135.       memset(&wc, 0, sizeof wc);
  136.       wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
  137.       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  138.       wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  139.       wc.lpfnWndProc = WndProc;
  140.       wc.lpszClassName = "wglpbuffer";
  141.       wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  142.       RegisterClass(&wc);
  143.       first = FALSE;
  144.    }
  145.  
  146.    dwExStyle = 0;
  147.    dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
  148.  
  149.    if (0) {
  150.       /*
  151.        * Don't hide the window -- useful for debugging what the application is
  152.        * drawing
  153.        */
  154.  
  155.       dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW;
  156.    } else {
  157.       dwStyle |= WS_POPUPWINDOW;
  158.    }
  159.  
  160.    rect.left = 0;
  161.    rect.top = 0;
  162.    rect.right = rect.left + iWidth;
  163.    rect.bottom = rect.top + iHeight;
  164.  
  165.    /*
  166.     * The CreateWindowEx parameters are the total (outside) dimensions of the
  167.     * window, which can vary with Windows version and user settings.  Use
  168.     * AdjustWindowRect to get the required total area for the given client area.
  169.     *
  170.     * AdjustWindowRectEx does not accept WS_OVERLAPPED style (which is defined
  171.     * as 0), which means we need to use some other style instead, e.g.,
  172.     * WS_OVERLAPPEDWINDOW or WS_POPUPWINDOW as above.
  173.     */
  174.  
  175.    AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
  176.  
  177.    hWnd = CreateWindowEx(dwExStyle,
  178.                          "wglpbuffer", /* wc.lpszClassName */
  179.                          NULL,
  180.                          dwStyle,
  181.                          CW_USEDEFAULT, /* x */
  182.                          CW_USEDEFAULT, /* y */
  183.                          rect.right - rect.left, /* width */
  184.                          rect.bottom - rect.top, /* height */
  185.                          NULL,
  186.                          NULL,
  187.                          NULL,
  188.                          NULL);
  189.    if (!hWnd) {
  190.       return 0;
  191.    }
  192.  
  193. #ifdef DEBUG
  194.    /*
  195.     * Verify the client area size matches the specified size.
  196.     */
  197.  
  198.    GetClientRect(hWnd, &rect);
  199.    assert(rect.left == 0);
  200.    assert(rect.top == 0);
  201.    assert(rect.right - rect.left == iWidth);
  202.    assert(rect.bottom - rect.top == iHeight);
  203. #endif
  204.  
  205.    hDC = GetDC(hWnd);
  206.    if (!hDC) {
  207.       return 0;
  208.    }
  209.  
  210.    /*
  211.     * We can't pass non-displayable pixel formats to GDI, which is why we
  212.     * create the framebuffer object before calling SetPixelFormat().
  213.     */
  214.    fb = stw_framebuffer_create(hDC, iPixelFormat);
  215.    if (!fb) {
  216.       SetLastError(ERROR_NO_SYSTEM_RESOURCES);
  217.       return NULL;
  218.    }
  219.  
  220.    fb->bPbuffer = TRUE;
  221.    iDisplayablePixelFormat = fb->iDisplayablePixelFormat;
  222.  
  223.    stw_framebuffer_release(fb);
  224.  
  225.    /*
  226.     * We need to set a displayable pixel format on the hidden window DC
  227.     * so that wglCreateContext and wglMakeCurrent are not overruled by GDI.
  228.     */
  229.    bRet = SetPixelFormat(hDC, iDisplayablePixelFormat, &pfd);
  230.    assert(bRet);
  231.  
  232.    return (HPBUFFERARB)fb;
  233. }
  234.  
  235.  
  236. HDC WINAPI
  237. wglGetPbufferDCARB(HPBUFFERARB hPbuffer)
  238. {
  239.    struct stw_framebuffer *fb;
  240.    HDC hDC;
  241.  
  242.    if (!hPbuffer) {
  243.       SetLastError(ERROR_INVALID_HANDLE);
  244.       return NULL;
  245.    }
  246.  
  247.    fb = (struct stw_framebuffer *)hPbuffer;
  248.  
  249.    hDC = GetDC(fb->hWnd);
  250.  
  251.    return hDC;
  252. }
  253.  
  254.  
  255. int WINAPI
  256. wglReleasePbufferDCARB(HPBUFFERARB hPbuffer,
  257.                        HDC hDC)
  258. {
  259.    struct stw_framebuffer *fb;
  260.  
  261.    if (!hPbuffer) {
  262.       SetLastError(ERROR_INVALID_HANDLE);
  263.       return 0;
  264.    }
  265.  
  266.    fb = (struct stw_framebuffer *)hPbuffer;
  267.  
  268.    return ReleaseDC(fb->hWnd, hDC);
  269. }
  270.  
  271.  
  272. BOOL WINAPI
  273. wglDestroyPbufferARB(HPBUFFERARB hPbuffer)
  274. {
  275.    struct stw_framebuffer *fb;
  276.  
  277.    if (!hPbuffer) {
  278.       SetLastError(ERROR_INVALID_HANDLE);
  279.       return FALSE;
  280.    }
  281.  
  282.    fb = (struct stw_framebuffer *)hPbuffer;
  283.  
  284.    /* This will destroy all our data */
  285.    return DestroyWindow(fb->hWnd);
  286. }
  287.  
  288.  
  289. BOOL WINAPI
  290. wglQueryPbufferARB(HPBUFFERARB hPbuffer,
  291.                    int iAttribute,
  292.                    int *piValue)
  293. {
  294.    struct stw_framebuffer *fb;
  295.  
  296.    if (!hPbuffer) {
  297.       SetLastError(ERROR_INVALID_HANDLE);
  298.       return FALSE;
  299.    }
  300.  
  301.    fb = (struct stw_framebuffer *)hPbuffer;
  302.  
  303.    switch (iAttribute) {
  304.    case WGL_PBUFFER_WIDTH_ARB:
  305.       *piValue = fb->width;
  306.       return TRUE;
  307.    case WGL_PBUFFER_HEIGHT_ARB:
  308.       *piValue = fb->height;
  309.       return TRUE;
  310.    case WGL_PBUFFER_LOST_ARB:
  311.       /* We assume that no content is ever lost due to display mode change */
  312.       *piValue = FALSE;
  313.       return TRUE;
  314.    default:
  315.       SetLastError(ERROR_INVALID_DATA);
  316.       return FALSE;
  317.    }
  318. }
  319.