1/************************************************************************** 2 * Copyright 2015 VMware, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27#include <windows.h> 28 29#define WGL_WGLEXT_PROTOTYPES 30 31#include <GL/gl.h> 32#include <GL/wglext.h> 33 34#include "state_tracker/st_copytex.h" 35 36#include "pipe/p_defines.h" 37#include "pipe/p_screen.h" 38#include "pipe/p_state.h" 39 40#include "stw_icd.h" 41#include "stw_context.h" 42#include "stw_device.h" 43#include "stw_pixelformat.h" 44#include "stw_framebuffer.h" 45#include "stw_st.h" 46 47 48/** Translate a WGL buffer name to a GLenum */ 49static GLenum 50translate_ibuffer(int iBuffer) 51{ 52 switch (iBuffer) { 53 case WGL_FRONT_LEFT_ARB: 54 return GL_FRONT_LEFT; 55 case WGL_BACK_LEFT_ARB: 56 return GL_BACK_LEFT; 57 case WGL_FRONT_RIGHT_ARB: 58 return GL_FRONT_RIGHT; 59 case WGL_BACK_RIGHT_ARB: 60 return GL_BACK_RIGHT; 61 case WGL_AUX0_ARB: 62 return GL_AUX0; 63 default: 64 return GL_NONE; 65 } 66} 67 68 69/** Translate a WGL texture target type to a GLenum */ 70static GLenum 71translate_target(unsigned textureTarget) 72{ 73 switch (textureTarget) { 74 case WGL_TEXTURE_1D_ARB: 75 return GL_TEXTURE_1D; 76 case WGL_TEXTURE_2D_ARB: 77 return GL_TEXTURE_2D; 78 case WGL_TEXTURE_CUBE_MAP_ARB: 79 return GL_TEXTURE_CUBE_MAP; 80 case WGL_NO_TEXTURE_ARB: 81 default: 82 return GL_NONE; 83 } 84} 85 86 87/** Translate a WGL texture format to a GLenum */ 88static GLenum 89translate_texture_format(unsigned wgl_format) 90{ 91 switch (wgl_format) { 92 case WGL_TEXTURE_RGB_ARB: 93 return GL_RGB; 94 case WGL_TEXTURE_RGBA_ARB: 95 return GL_RGBA; 96 case WGL_NO_TEXTURE_ARB: 97 default: 98 return GL_NONE; 99 } 100} 101 102 103BOOL WINAPI 104wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) 105{ 106 HDC prevDrawable = stw_get_current_dc(); 107 HDC dc; 108 struct stw_context *curctx = stw_current_context(); 109 struct stw_framebuffer *fb; 110 GLenum texFormat, srcBuffer, target; 111 boolean retVal; 112 int pixelFormatSave; 113 114 /* 115 * Implementation notes: 116 * Ideally, we'd implement this function with the 117 * st_context_iface::teximage() function which replaces a specific 118 * texture image with a different resource (the pbuffer). 119 * The main problem however, is the pbuffer image is upside down relative 120 * to the texture image. 121 * Window system drawing surfaces (windows & pbuffers) are "top to bottom" 122 * while OpenGL texture images are "bottom to top". One possible solution 123 * to this is to invert rendering to pbuffers (as we do for renderbuffers) 124 * but that could lead to other issues (and would require extensive 125 * testing). 126 * 127 * The simple alternative is to use a copy-based approach which copies the 128 * pbuffer image into the texture via glCopyTex[Sub]Image. That's what 129 * we do here. 130 */ 131 132 fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); 133 if (!fb) { 134 debug_printf("Invalid pbuffer handle in wglBindTexImageARB()\n"); 135 SetLastError(ERROR_INVALID_HANDLE); 136 return FALSE; 137 } 138 139 srcBuffer = translate_ibuffer(iBuffer); 140 if (srcBuffer == GL_NONE) { 141 debug_printf("Invalid buffer 0x%x in wglBindTexImageARB()\n", iBuffer); 142 SetLastError(ERROR_INVALID_DATA); 143 return FALSE; 144 } 145 146 target = translate_target(fb->textureTarget); 147 if (target == GL_NONE) { 148 debug_printf("no texture target in wglBindTexImageARB()\n"); 149 return FALSE; 150 } 151 152 texFormat = translate_texture_format(fb->textureFormat); 153 if (texFormat == GL_NONE) { 154 debug_printf("no texture format in wglBindTexImageARB()\n"); 155 return FALSE; 156 } 157 158 /* 159 * Bind the pbuffer surface so we can read/copy from it. 160 * 161 * Before we can call stw_make_current() we have to temporarily 162 * change the pbuffer's pixel format to match the context to avoid 163 * an error condition. After the stw_make_current() we restore the 164 * buffer's pixel format. 165 */ 166 pixelFormatSave = fb->iPixelFormat; 167 fb->iPixelFormat = curctx->iPixelFormat; 168 dc = wglGetPbufferDCARB(hPbuffer); 169 retVal = stw_make_current(dc, curctx->dhglrc); 170 fb->iPixelFormat = pixelFormatSave; 171 if (!retVal) { 172 debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n"); 173 wglReleasePbufferDCARB(hPbuffer, dc); 174 return FALSE; 175 } 176 177 st_copy_framebuffer_to_texture(srcBuffer, fb->width, fb->height, 178 target, fb->textureLevel, 179 fb->textureFace, texFormat); 180 181 /* rebind previous drawing surface */ 182 retVal = stw_make_current(prevDrawable, curctx->dhglrc); 183 if (!retVal) { 184 debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n"); 185 } 186 187 wglReleasePbufferDCARB(hPbuffer, dc); 188 189 return retVal; 190} 191 192 193BOOL WINAPI 194wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) 195{ 196 struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); 197 GLenum srcBuffer; 198 199 /* nothing to do here, but we do error checking anyway */ 200 201 if (!fb) { 202 debug_printf("Invalid pbuffer handle in wglReleaseTexImageARB()\n"); 203 SetLastError(ERROR_INVALID_HANDLE); 204 return FALSE; 205 } 206 207 srcBuffer = translate_ibuffer(iBuffer); 208 if (srcBuffer == GL_NONE) { 209 debug_printf("Invalid buffer 0x%x in wglReleaseTexImageARB()\n", iBuffer); 210 SetLastError(ERROR_INVALID_DATA); 211 return FALSE; 212 } 213 214 return TRUE; 215} 216 217 218BOOL WINAPI 219wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList) 220{ 221 struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); 222 int face, i; 223 224 if (!fb) { 225 SetLastError(ERROR_INVALID_HANDLE); 226 return FALSE; 227 } 228 229 for (i = 0; piAttribList[i]; i += 2) { 230 switch (piAttribList[i]) { 231 case WGL_MIPMAP_LEVEL_ARB: 232 fb->textureLevel = piAttribList[i+1]; 233 break; 234 case WGL_CUBE_MAP_FACE_ARB: 235 face = piAttribList[i+1]; 236 if (face >= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 237 face <= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 238 fb->textureFace = face - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; 239 } 240 else { 241 debug_printf("Invalid cube face 0x%x in " 242 "wglSetPbufferAttribARB()\n", 243 piAttribList[i]); 244 SetLastError(ERROR_INVALID_DATA); 245 return FALSE; 246 } 247 break; 248 default: 249 debug_printf("Invalid attribute 0x%x in wglSetPbufferAttribARB()\n", 250 piAttribList[i]); 251 SetLastError(ERROR_INVALID_DATA); 252 return FALSE; 253 } 254 } 255 256 return TRUE; 257} 258