diff options
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_ext_rendertexture.c | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c b/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c new file mode 100644 index 00000000000..18df2ebd1fa --- /dev/null +++ b/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c @@ -0,0 +1,252 @@ +/************************************************************************** + * Copyright 2015 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> + +#define WGL_WGLEXT_PROTOTYPES + +#include <GL/gl.h> +#include <GL/wglext.h> + +#include "state_tracker/st_copytex.h" + +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" + +#include "stw_icd.h" +#include "stw_context.h" +#include "stw_device.h" +#include "stw_pixelformat.h" +#include "stw_framebuffer.h" +#include "stw_st.h" + + +/** Translate a WGL buffer name to a GLenum */ +static GLenum +translate_ibuffer(int iBuffer) +{ + switch (iBuffer) { + case WGL_FRONT_LEFT_ARB: + return GL_FRONT_LEFT; + case WGL_BACK_LEFT_ARB: + return GL_BACK_LEFT; + case WGL_FRONT_RIGHT_ARB: + return GL_FRONT_RIGHT; + case WGL_BACK_RIGHT_ARB: + return GL_BACK_RIGHT; + case WGL_AUX0_ARB: + return GL_AUX0; + default: + return GL_NONE; + } +} + + +/** Translate a WGL texture target type to a GLenum */ +static GLenum +translate_target(unsigned textureTarget) +{ + switch (textureTarget) { + case WGL_TEXTURE_1D_ARB: + return GL_TEXTURE_1D; + case WGL_TEXTURE_2D_ARB: + return GL_TEXTURE_2D; + case WGL_TEXTURE_CUBE_MAP_ARB: + return GL_TEXTURE_CUBE_MAP; + case WGL_NO_TEXTURE_ARB: + default: + return GL_NONE; + } +} + + +/** Translate a WGL texture format to a GLenum */ +static GLenum +translate_texture_format(unsigned wgl_format) +{ + switch (wgl_format) { + case WGL_TEXTURE_RGB_ARB: + return GL_RGB; + case WGL_TEXTURE_RGBA_ARB: + return GL_RGBA; + case WGL_NO_TEXTURE_ARB: + default: + return GL_NONE; + } +} + + +BOOL WINAPI +wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) +{ + HDC prevDrawable = stw_get_current_dc(); + struct stw_context *curctx = stw_current_context(); + struct stw_framebuffer *fb; + GLenum texFormat, srcBuffer, target; + boolean retVal; + int pixelFormatSave; + + /* + * Implementation notes: + * Ideally, we'd implement this function with the + * st_context_iface::teximage() function which replaces a specific + * texture image with a different resource (the pbuffer). + * The main problem however, is the pbuffer image is upside down relative + * to the texture image. + * Window system drawing surfaces (windows & pbuffers) are "top to bottom" + * while OpenGL texture images are "bottom to top". One possible solution + * to this is to invert rendering to pbuffers (as we do for renderbuffers) + * but that could lead to other issues (and would require extensive + * testing). + * + * The simple alternative is to use a copy-based approach which copies the + * pbuffer image into the texture via glCopyTex[Sub]Image. That's what + * we do here. + */ + + fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + if (!fb) { + debug_printf("Invalid pbuffer handle in wglBindTexImageARB()\n"); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + srcBuffer = translate_ibuffer(iBuffer); + if (srcBuffer == GL_NONE) { + debug_printf("Invalid buffer 0x%x in wglBindTexImageARB()\n", iBuffer); + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + + target = translate_target(fb->textureTarget); + if (target == GL_NONE) { + debug_printf("no texture target in wglBindTexImageARB()\n"); + return FALSE; + } + + texFormat = translate_texture_format(fb->textureFormat); + if (texFormat == GL_NONE) { + debug_printf("no texture format in wglBindTexImageARB()\n"); + return FALSE; + } + + /* + * Bind the pbuffer surface so we can read/copy from it. + * + * Before we can call stw_make_current() we have to temporarily + * change the pbuffer's pixel format to match the context to avoid + * an error condition. After the stw_make_current() we restore the + * buffer's pixel format. + */ + pixelFormatSave = fb->iPixelFormat; + fb->iPixelFormat = curctx->iPixelFormat; + retVal = stw_make_current(wglGetPbufferDCARB(hPbuffer), curctx->dhglrc); + fb->iPixelFormat = pixelFormatSave; + if (!retVal) { + debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n"); + return FALSE; + } + + st_copy_framebuffer_to_texture(srcBuffer, fb->width, fb->height, + target, fb->textureLevel, + fb->textureFace, texFormat); + + /* rebind previous drawing surface */ + retVal = stw_make_current(prevDrawable, curctx->dhglrc); + if (!retVal) { + debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n"); + } + + return retVal; +} + + +BOOL WINAPI +wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) +{ + struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + GLenum srcBuffer; + + /* nothing to do here, but we do error checking anyway */ + + if (!fb) { + debug_printf("Invalid pbuffer handle in wglReleaseTexImageARB()\n"); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + srcBuffer = translate_ibuffer(iBuffer); + if (srcBuffer == GL_NONE) { + debug_printf("Invalid buffer 0x%x in wglReleaseTexImageARB()\n", iBuffer); + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + + return TRUE; +} + + +BOOL WINAPI +wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList) +{ + struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + int face, i; + + if (!fb) { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + for (i = 0; piAttribList[i]; i += 2) { + switch (piAttribList[i]) { + case WGL_MIPMAP_LEVEL_ARB: + fb->textureLevel = piAttribList[i+1]; + break; + case WGL_CUBE_MAP_FACE_ARB: + face = piAttribList[i+1]; + if (face >= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + face <= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + fb->textureFace = face - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; + } + else { + debug_printf("Invalid cube face 0x%x in " + "wglSetPbufferAttribARB()\n", + piAttribList[i]); + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + break; + default: + debug_printf("Invalid attribute 0x%x in wglSetPbufferAttribARB()\n", + piAttribList[i]); + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + } + + return TRUE; +} |