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