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