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 "gldrv.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 struct stw_context *curctx = stw_current_context(); 107 struct stw_framebuffer *fb, *old_fb, *old_fbRead; 108 GLenum texFormat, srcBuffer, target; 109 boolean retVal; 110 int pixelFormatSave; 111 112 /* 113 * Implementation notes: 114 * Ideally, we'd implement this function with the 115 * st_context_iface::teximage() function which replaces a specific 116 * texture image with a different resource (the pbuffer). 117 * The main problem however, is the pbuffer image is upside down relative 118 * to the texture image. 119 * Window system drawing surfaces (windows & pbuffers) are "top to bottom" 120 * while OpenGL texture images are "bottom to top". One possible solution 121 * to this is to invert rendering to pbuffers (as we do for renderbuffers) 122 * but that could lead to other issues (and would require extensive 123 * testing). 124 * 125 * The simple alternative is to use a copy-based approach which copies the 126 * pbuffer image into the texture via glCopyTex[Sub]Image. That's what 127 * we do here. 128 */ 129 130 if (!curctx) { 131 debug_printf("No rendering context in wglBindTexImageARB()\n"); 132 SetLastError(ERROR_INVALID_OPERATION); 133 return FALSE; 134 } 135 136 fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); 137 if (!fb) { 138 debug_printf("Invalid pbuffer handle in wglBindTexImageARB()\n"); 139 SetLastError(ERROR_INVALID_HANDLE); 140 return FALSE; 141 } 142 143 srcBuffer = translate_ibuffer(iBuffer); 144 if (srcBuffer == GL_NONE) { 145 debug_printf("Invalid buffer 0x%x in wglBindTexImageARB()\n", iBuffer); 146 SetLastError(ERROR_INVALID_DATA); 147 return FALSE; 148 } 149 150 target = translate_target(fb->textureTarget); 151 if (target == GL_NONE) { 152 debug_printf("no texture target in wglBindTexImageARB()\n"); 153 return FALSE; 154 } 155 156 texFormat = translate_texture_format(fb->textureFormat); 157 if (texFormat == GL_NONE) { 158 debug_printf("no texture format in wglBindTexImageARB()\n"); 159 return FALSE; 160 } 161 162 old_fb = curctx->current_framebuffer; 163 old_fbRead = curctx->current_read_framebuffer; 164 165 /* 166 * Bind the pbuffer surface so we can read/copy from it. 167 * 168 * Before we can call stw_make_current() we have to temporarily 169 * change the pbuffer's pixel format to match the context to avoid 170 * an error condition. After the stw_make_current() we restore the 171 * buffer's pixel format. 172 */ 173 pixelFormatSave = fb->iPixelFormat; 174 fb->iPixelFormat = curctx->iPixelFormat; 175 retVal = stw_make_current(fb, fb, curctx); 176 fb->iPixelFormat = pixelFormatSave; 177 if (!retVal) { 178 debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n"); 179 return FALSE; 180 } 181 182 st_copy_framebuffer_to_texture(srcBuffer, fb->width, fb->height, 183 target, fb->textureLevel, 184 fb->textureFace, texFormat); 185 186 /* rebind previous drawing surface */ 187 retVal = stw_make_current(old_fb, old_fbRead, curctx); 188 if (!retVal) { 189 debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n"); 190 } 191 192 return retVal; 193} 194 195 196BOOL WINAPI 197wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) 198{ 199 struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); 200 GLenum srcBuffer; 201 202 /* nothing to do here, but we do error checking anyway */ 203 204 if (!fb) { 205 debug_printf("Invalid pbuffer handle in wglReleaseTexImageARB()\n"); 206 SetLastError(ERROR_INVALID_HANDLE); 207 return FALSE; 208 } 209 210 srcBuffer = translate_ibuffer(iBuffer); 211 if (srcBuffer == GL_NONE) { 212 debug_printf("Invalid buffer 0x%x in wglReleaseTexImageARB()\n", iBuffer); 213 SetLastError(ERROR_INVALID_DATA); 214 return FALSE; 215 } 216 217 return TRUE; 218} 219 220 221BOOL WINAPI 222wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList) 223{ 224 struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); 225 int face, i; 226 227 if (!fb) { 228 SetLastError(ERROR_INVALID_HANDLE); 229 return FALSE; 230 } 231 232 for (i = 0; piAttribList[i]; i += 2) { 233 switch (piAttribList[i]) { 234 case WGL_MIPMAP_LEVEL_ARB: 235 fb->textureLevel = piAttribList[i+1]; 236 break; 237 case WGL_CUBE_MAP_FACE_ARB: 238 face = piAttribList[i+1]; 239 if (face >= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 240 face <= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 241 fb->textureFace = face - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; 242 } 243 else { 244 debug_printf("Invalid cube face 0x%x in " 245 "wglSetPbufferAttribARB()\n", 246 piAttribList[i]); 247 SetLastError(ERROR_INVALID_DATA); 248 return FALSE; 249 } 250 break; 251 default: 252 debug_printf("Invalid attribute 0x%x in wglSetPbufferAttribARB()\n", 253 piAttribList[i]); 254 SetLastError(ERROR_INVALID_DATA); 255 return FALSE; 256 } 257 } 258 259 return TRUE; 260} 261