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