stw_ext_pbuffer.c revision f4e392bf8d35a87f84c8a58f9d2bd174ec29ebd9
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
43HPBUFFERARB WINAPI
44wglCreatePbufferARB(HDC _hDC,
45                    int iPixelFormat,
46                    int iWidth,
47                    int iHeight,
48                    const int *piAttribList)
49{
50   static boolean first = TRUE;
51   const int *piAttrib;
52   int useLargest = 0;
53   const struct stw_pixelformat_info *info;
54   struct stw_framebuffer *fb;
55   DWORD dwExStyle;
56   DWORD dwStyle;
57   RECT rect;
58   HWND hWnd;
59   HDC hDC;
60
61   info = stw_pixelformat_get_info(iPixelFormat);
62   if (!info) {
63      SetLastError(ERROR_INVALID_PIXEL_FORMAT);
64      return 0;
65   }
66
67   if (iWidth <= 0 || iHeight <= 0) {
68      SetLastError(ERROR_INVALID_DATA);
69      return 0;
70   }
71
72   for (piAttrib = piAttribList; *piAttrib; piAttrib++) {
73      switch (*piAttrib) {
74      case WGL_PBUFFER_LARGEST_ARB:
75         piAttrib++;
76         useLargest = *piAttrib;
77         break;
78      default:
79         SetLastError(ERROR_INVALID_DATA);
80         return 0;
81      }
82   }
83
84   if (iWidth > stw_dev->max_2d_length) {
85      if (useLargest) {
86         iWidth = stw_dev->max_2d_length;
87      } else {
88         SetLastError(ERROR_NO_SYSTEM_RESOURCES);
89         return 0;
90      }
91   }
92
93   if (iHeight > stw_dev->max_2d_length) {
94      if (useLargest) {
95         iHeight = stw_dev->max_2d_length;
96      } else {
97         SetLastError(ERROR_NO_SYSTEM_RESOURCES);
98         return 0;
99      }
100   }
101
102   /*
103    * Implement pbuffers through invisible windows
104    */
105
106   if (first) {
107      WNDCLASS wc;
108      memset(&wc, 0, sizeof wc);
109      wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
110      wc.hCursor = LoadCursor(NULL, IDC_ARROW);
111      wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
112      wc.lpfnWndProc = DefWindowProc;
113      wc.lpszClassName = "wglpbuffer";
114      wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
115      RegisterClass(&wc);
116      first = FALSE;
117   }
118
119   dwExStyle = 0;
120   dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
121
122   if (0) {
123      /*
124       * Don't hide the window -- useful for debugging what the application is
125       * drawing
126       */
127
128      dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW;
129   } else {
130      dwStyle |= WS_POPUPWINDOW;
131   }
132
133   rect.left = 0;
134   rect.top = 0;
135   rect.right = rect.left + iWidth;
136   rect.bottom = rect.top + iHeight;
137
138   /*
139    * The CreateWindowEx parameters are the total (outside) dimensions of the
140    * window, which can vary with Windows version and user settings.  Use
141    * AdjustWindowRect to get the required total area for the given client area.
142    *
143    * AdjustWindowRectEx does not accept WS_OVERLAPPED style (which is defined
144    * as 0), which means we need to use some other style instead, e.g.,
145    * WS_OVERLAPPEDWINDOW or WS_POPUPWINDOW as above.
146    */
147
148   AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
149
150   hWnd = CreateWindowEx(dwExStyle,
151                         "wglpbuffer", /* wc.lpszClassName */
152                         NULL,
153                         dwStyle,
154                         CW_USEDEFAULT, /* x */
155                         CW_USEDEFAULT, /* y */
156                         rect.right - rect.left, /* width */
157                         rect.bottom - rect.top, /* height */
158                         NULL,
159                         NULL,
160                         NULL,
161                         NULL);
162   if (!hWnd) {
163      return 0;
164   }
165
166#ifdef DEBUG
167   /*
168    * Verify the client area size matches the specified size.
169    */
170
171   GetClientRect(hWnd, &rect);
172   assert(rect.left == 0);
173   assert(rect.top == 0);
174   assert(rect.right - rect.left == iWidth);
175   assert(rect.bottom - rect.top == iHeight);
176#endif
177
178   hDC = GetDC(hWnd);
179   if (!hDC) {
180      return 0;
181   }
182
183   SetPixelFormat(hDC, iPixelFormat, &info->pfd);
184
185   fb = stw_framebuffer_create(hDC, iPixelFormat);
186   if (!fb) {
187      SetLastError(ERROR_NO_SYSTEM_RESOURCES);
188   }
189
190   return (HPBUFFERARB)fb;
191}
192
193
194HDC WINAPI
195wglGetPbufferDCARB(HPBUFFERARB hPbuffer)
196{
197   struct stw_framebuffer *fb;
198   HDC hDC;
199
200   fb = (struct stw_framebuffer *)hPbuffer;
201
202   hDC = GetDC(fb->hWnd);
203   SetPixelFormat(hDC, fb->iPixelFormat, &fb->pfi->pfd);
204
205   return hDC;
206}
207
208
209int WINAPI
210wglReleasePbufferDCARB(HPBUFFERARB hPbuffer,
211                       HDC hDC)
212{
213   struct stw_framebuffer *fb;
214
215   fb = (struct stw_framebuffer *)hPbuffer;
216
217   return ReleaseDC(fb->hWnd, hDC);
218}
219
220
221BOOL WINAPI
222wglDestroyPbufferARB(HPBUFFERARB hPbuffer)
223{
224   struct stw_framebuffer *fb;
225
226   fb = (struct stw_framebuffer *)hPbuffer;
227
228   /* This will destroy all our data */
229   return DestroyWindow(fb->hWnd);
230}
231
232
233BOOL WINAPI
234wglQueryPbufferARB(HPBUFFERARB hPbuffer,
235                   int iAttribute,
236                   int *piValue)
237{
238   struct stw_framebuffer *fb;
239
240   fb = (struct stw_framebuffer *)hPbuffer;
241
242   switch (iAttribute) {
243   case WGL_PBUFFER_WIDTH_ARB:
244      *piValue = fb->width;
245      return TRUE;
246   case WGL_PBUFFER_HEIGHT_ARB:
247      *piValue = fb->width;
248      return TRUE;
249   case WGL_PBUFFER_LOST_ARB:
250      /* We assume that no content is ever lost due to display mode change */
251      *piValue = FALSE;
252      return TRUE;
253   default:
254      SetLastError(ERROR_INVALID_DATA);
255      return FALSE;
256   }
257}
258