Path: blob/21.2-virgl/src/gallium/frontends/wgl/stw_ext_rendertexture.c
4561 views
/**************************************************************************1* Copyright 2015 VMware, Inc.2* All Rights Reserved.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the6* "Software"), to deal in the Software without restriction, including7* without limitation the rights to use, copy, modify, merge, publish,8* distribute, sub license, and/or sell copies of the Software, and to9* permit persons to whom the Software is furnished to do so, subject to10* the following conditions:11*12* The above copyright notice and this permission notice (including the13* next paragraph) shall be included in all copies or substantial portions14* of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS17* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.19* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR20* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,21* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE22* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.23*24**************************************************************************/2526#include <windows.h>2728#define WGL_WGLEXT_PROTOTYPES2930#include <GL/gl.h>31#include <GL/wglext.h>3233#include "state_tracker/st_copytex.h"3435#include "pipe/p_defines.h"36#include "pipe/p_screen.h"37#include "pipe/p_state.h"3839#include "gldrv.h"40#include "stw_context.h"41#include "stw_device.h"42#include "stw_pixelformat.h"43#include "stw_framebuffer.h"44#include "stw_st.h"454647/** Translate a WGL buffer name to a GLenum */48static GLenum49translate_ibuffer(int iBuffer)50{51switch (iBuffer) {52case WGL_FRONT_LEFT_ARB:53return GL_FRONT_LEFT;54case WGL_BACK_LEFT_ARB:55return GL_BACK_LEFT;56case WGL_FRONT_RIGHT_ARB:57return GL_FRONT_RIGHT;58case WGL_BACK_RIGHT_ARB:59return GL_BACK_RIGHT;60case WGL_AUX0_ARB:61return GL_AUX0;62default:63return GL_NONE;64}65}666768/** Translate a WGL texture target type to a GLenum */69static GLenum70translate_target(unsigned textureTarget)71{72switch (textureTarget) {73case WGL_TEXTURE_1D_ARB:74return GL_TEXTURE_1D;75case WGL_TEXTURE_2D_ARB:76return GL_TEXTURE_2D;77case WGL_TEXTURE_CUBE_MAP_ARB:78return GL_TEXTURE_CUBE_MAP;79case WGL_NO_TEXTURE_ARB:80default:81return GL_NONE;82}83}848586/** Translate a WGL texture format to a GLenum */87static GLenum88translate_texture_format(unsigned wgl_format)89{90switch (wgl_format) {91case WGL_TEXTURE_RGB_ARB:92return GL_RGB;93case WGL_TEXTURE_RGBA_ARB:94return GL_RGBA;95case WGL_NO_TEXTURE_ARB:96default:97return GL_NONE;98}99}100101102BOOL WINAPI103wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)104{105HDC prevDrawable = stw_get_current_dc();106HDC prevReadable = stw_get_current_read_dc();107HDC dc;108struct stw_context *curctx = stw_current_context();109struct stw_framebuffer *fb;110GLenum texFormat, srcBuffer, target;111boolean retVal;112int pixelFormatSave;113114/*115* Implementation notes:116* Ideally, we'd implement this function with the117* st_context_iface::teximage() function which replaces a specific118* texture image with a different resource (the pbuffer).119* The main problem however, is the pbuffer image is upside down relative120* 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 solution123* to this is to invert rendering to pbuffers (as we do for renderbuffers)124* but that could lead to other issues (and would require extensive125* testing).126*127* The simple alternative is to use a copy-based approach which copies the128* pbuffer image into the texture via glCopyTex[Sub]Image. That's what129* we do here.130*/131132if (!curctx) {133debug_printf("No rendering context in wglBindTexImageARB()\n");134SetLastError(ERROR_INVALID_OPERATION);135return FALSE;136}137138fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);139if (!fb) {140debug_printf("Invalid pbuffer handle in wglBindTexImageARB()\n");141SetLastError(ERROR_INVALID_HANDLE);142return FALSE;143}144145srcBuffer = translate_ibuffer(iBuffer);146if (srcBuffer == GL_NONE) {147debug_printf("Invalid buffer 0x%x in wglBindTexImageARB()\n", iBuffer);148SetLastError(ERROR_INVALID_DATA);149return FALSE;150}151152target = translate_target(fb->textureTarget);153if (target == GL_NONE) {154debug_printf("no texture target in wglBindTexImageARB()\n");155return FALSE;156}157158texFormat = translate_texture_format(fb->textureFormat);159if (texFormat == GL_NONE) {160debug_printf("no texture format in wglBindTexImageARB()\n");161return FALSE;162}163164/*165* Bind the pbuffer surface so we can read/copy from it.166*167* Before we can call stw_make_current() we have to temporarily168* change the pbuffer's pixel format to match the context to avoid169* an error condition. After the stw_make_current() we restore the170* buffer's pixel format.171*/172pixelFormatSave = fb->iPixelFormat;173fb->iPixelFormat = curctx->iPixelFormat;174dc = wglGetPbufferDCARB(hPbuffer);175retVal = stw_make_current(dc, dc, curctx->dhglrc);176fb->iPixelFormat = pixelFormatSave;177if (!retVal) {178debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n");179wglReleasePbufferDCARB(hPbuffer, dc);180return FALSE;181}182183st_copy_framebuffer_to_texture(srcBuffer, fb->width, fb->height,184target, fb->textureLevel,185fb->textureFace, texFormat);186187/* rebind previous drawing surface */188retVal = stw_make_current(prevDrawable, prevReadable, curctx->dhglrc);189if (!retVal) {190debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n");191}192193wglReleasePbufferDCARB(hPbuffer, dc);194195return retVal;196}197198199BOOL WINAPI200wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)201{202struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);203GLenum srcBuffer;204205/* nothing to do here, but we do error checking anyway */206207if (!fb) {208debug_printf("Invalid pbuffer handle in wglReleaseTexImageARB()\n");209SetLastError(ERROR_INVALID_HANDLE);210return FALSE;211}212213srcBuffer = translate_ibuffer(iBuffer);214if (srcBuffer == GL_NONE) {215debug_printf("Invalid buffer 0x%x in wglReleaseTexImageARB()\n", iBuffer);216SetLastError(ERROR_INVALID_DATA);217return FALSE;218}219220return TRUE;221}222223224BOOL WINAPI225wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList)226{227struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);228int face, i;229230if (!fb) {231SetLastError(ERROR_INVALID_HANDLE);232return FALSE;233}234235for (i = 0; piAttribList[i]; i += 2) {236switch (piAttribList[i]) {237case WGL_MIPMAP_LEVEL_ARB:238fb->textureLevel = piAttribList[i+1];239break;240case WGL_CUBE_MAP_FACE_ARB:241face = piAttribList[i+1];242if (face >= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&243face <= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {244fb->textureFace = face - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;245}246else {247debug_printf("Invalid cube face 0x%x in "248"wglSetPbufferAttribARB()\n",249piAttribList[i]);250SetLastError(ERROR_INVALID_DATA);251return FALSE;252}253break;254default:255debug_printf("Invalid attribute 0x%x in wglSetPbufferAttribARB()\n",256piAttribList[i]);257SetLastError(ERROR_INVALID_DATA);258return FALSE;259}260}261262return TRUE;263}264265266