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