Path: blob/21.2-virgl/src/gallium/frontends/wgl/stw_ext_pbuffer.c
4561 views
/**************************************************************************1*2* Copyright 2010 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include <windows.h>2829#define WGL_WGLEXT_PROTOTYPES3031#include <GL/gl.h>32#include <GL/wglext.h>3334#include "pipe/p_defines.h"35#include "pipe/p_screen.h"3637#include "util/u_debug.h"3839#include "stw_device.h"40#include "stw_pixelformat.h"41#include "stw_framebuffer.h"424344#define LARGE_WINDOW_SIZE 60000454647static LRESULT CALLBACK48WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)49{50MINMAXINFO *pMMI;51switch (uMsg) {52case WM_GETMINMAXINFO:53// Allow to create a window bigger than the desktop54pMMI = (MINMAXINFO *)lParam;55pMMI->ptMaxSize.x = LARGE_WINDOW_SIZE;56pMMI->ptMaxSize.y = LARGE_WINDOW_SIZE;57pMMI->ptMaxTrackSize.x = LARGE_WINDOW_SIZE;58pMMI->ptMaxTrackSize.y = LARGE_WINDOW_SIZE;59break;60default:61break;62}6364return DefWindowProc(hWnd, uMsg, wParam, lParam);65}666768HPBUFFERARB WINAPI69wglCreatePbufferARB(HDC hCurrentDC,70int iPixelFormat,71int iWidth,72int iHeight,73const int *piAttribList)74{75static boolean first = TRUE;76const int *piAttrib;77int useLargest = 0;78const struct stw_pixelformat_info *info;79struct stw_framebuffer *fb;80DWORD dwExStyle;81DWORD dwStyle;82RECT rect;83HWND hWnd;84HDC hDC;85int iDisplayablePixelFormat;86PIXELFORMATDESCRIPTOR pfd;87BOOL bRet;88int textureFormat = WGL_NO_TEXTURE_ARB;89int textureTarget = WGL_NO_TEXTURE_ARB;90BOOL textureMipmap = FALSE;9192info = stw_pixelformat_get_info(iPixelFormat);93if (!info) {94SetLastError(ERROR_INVALID_PIXEL_FORMAT);95return 0;96}9798if (iWidth <= 0 || iHeight <= 0) {99SetLastError(ERROR_INVALID_DATA);100return 0;101}102103if (piAttribList) {104for (piAttrib = piAttribList; *piAttrib; piAttrib++) {105switch (*piAttrib) {106case WGL_PBUFFER_LARGEST_ARB:107piAttrib++;108useLargest = *piAttrib;109break;110case WGL_TEXTURE_FORMAT_ARB:111/* WGL_ARB_render_texture */112piAttrib++;113textureFormat = *piAttrib;114if (textureFormat != WGL_TEXTURE_RGB_ARB &&115textureFormat != WGL_TEXTURE_RGBA_ARB &&116textureFormat != WGL_NO_TEXTURE_ARB) {117SetLastError(ERROR_INVALID_DATA);118return 0;119}120break;121case WGL_TEXTURE_TARGET_ARB:122/* WGL_ARB_render_texture */123piAttrib++;124textureTarget = *piAttrib;125if (textureTarget != WGL_TEXTURE_CUBE_MAP_ARB &&126textureTarget != WGL_TEXTURE_1D_ARB &&127textureTarget != WGL_TEXTURE_2D_ARB &&128textureTarget != WGL_NO_TEXTURE_ARB) {129SetLastError(ERROR_INVALID_DATA);130return 0;131}132break;133case WGL_MIPMAP_TEXTURE_ARB:134/* WGL_ARB_render_texture */135piAttrib++;136textureMipmap = !!*piAttrib;137break;138default:139SetLastError(ERROR_INVALID_DATA);140debug_printf("wgl: Unsupported attribute 0x%x in %s\n",141*piAttrib, __func__);142return 0;143}144}145}146147if (iWidth > stw_dev->max_2d_length) {148if (useLargest) {149iWidth = stw_dev->max_2d_length;150} else {151SetLastError(ERROR_NO_SYSTEM_RESOURCES);152return 0;153}154}155156if (iHeight > stw_dev->max_2d_length) {157if (useLargest) {158iHeight = stw_dev->max_2d_length;159} else {160SetLastError(ERROR_NO_SYSTEM_RESOURCES);161return 0;162}163}164165/*166* Implement pbuffers through invisible windows167*/168169if (first) {170WNDCLASS wc;171memset(&wc, 0, sizeof wc);172wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);173wc.hCursor = LoadCursor(NULL, IDC_ARROW);174wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);175wc.lpfnWndProc = WndProc;176wc.lpszClassName = "wglpbuffer";177wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;178RegisterClass(&wc);179first = FALSE;180}181182dwExStyle = 0;183dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;184185if (0) {186/*187* Don't hide the window -- useful for debugging what the application is188* drawing189*/190191dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW;192} else {193dwStyle |= WS_POPUPWINDOW;194}195196rect.left = 0;197rect.top = 0;198rect.right = rect.left + iWidth;199rect.bottom = rect.top + iHeight;200201/*202* The CreateWindowEx parameters are the total (outside) dimensions of the203* window, which can vary with Windows version and user settings. Use204* AdjustWindowRect to get the required total area for the given client area.205*206* AdjustWindowRectEx does not accept WS_OVERLAPPED style (which is defined207* as 0), which means we need to use some other style instead, e.g.,208* WS_OVERLAPPEDWINDOW or WS_POPUPWINDOW as above.209*/210211AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);212213hWnd = CreateWindowEx(dwExStyle,214"wglpbuffer", /* wc.lpszClassName */215NULL,216dwStyle,217CW_USEDEFAULT, /* x */218CW_USEDEFAULT, /* y */219rect.right - rect.left, /* width */220rect.bottom - rect.top, /* height */221NULL,222NULL,223NULL,224NULL);225if (!hWnd) {226return 0;227}228229#ifdef DEBUG230/*231* Verify the client area size matches the specified size.232*/233234GetClientRect(hWnd, &rect);235assert(rect.left == 0);236assert(rect.top == 0);237assert(rect.right - rect.left == iWidth);238assert(rect.bottom - rect.top == iHeight);239#endif240241hDC = GetDC(hWnd);242if (!hDC) {243return 0;244}245246/*247* We can't pass non-displayable pixel formats to GDI, which is why we248* create the framebuffer object before calling SetPixelFormat().249*/250fb = stw_framebuffer_create(hDC, iPixelFormat);251if (!fb) {252SetLastError(ERROR_NO_SYSTEM_RESOURCES);253return NULL;254}255256fb->bPbuffer = TRUE;257258/* WGL_ARB_render_texture fields */259fb->textureTarget = textureTarget;260fb->textureFormat = textureFormat;261fb->textureMipmap = textureMipmap;262263iDisplayablePixelFormat = fb->iDisplayablePixelFormat;264265stw_framebuffer_unlock(fb);266267/*268* We need to set a displayable pixel format on the hidden window DC269* so that wglCreateContext and wglMakeCurrent are not overruled by GDI.270*/271bRet = SetPixelFormat(hDC, iDisplayablePixelFormat, &pfd);272assert(bRet);273274return (HPBUFFERARB)fb;275}276277278HDC WINAPI279wglGetPbufferDCARB(HPBUFFERARB hPbuffer)280{281struct stw_framebuffer *fb;282HDC hDC;283284if (!hPbuffer) {285SetLastError(ERROR_INVALID_HANDLE);286return NULL;287}288289fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);290291hDC = GetDC(fb->hWnd);292293return hDC;294}295296297int WINAPI298wglReleasePbufferDCARB(HPBUFFERARB hPbuffer,299HDC hDC)300{301struct stw_framebuffer *fb;302303if (!hPbuffer) {304SetLastError(ERROR_INVALID_HANDLE);305return 0;306}307308fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);309310return ReleaseDC(fb->hWnd, hDC);311}312313314BOOL WINAPI315wglDestroyPbufferARB(HPBUFFERARB hPbuffer)316{317struct stw_framebuffer *fb;318319if (!hPbuffer) {320SetLastError(ERROR_INVALID_HANDLE);321return FALSE;322}323324fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);325326/* This will destroy all our data */327return DestroyWindow(fb->hWnd);328}329330331BOOL WINAPI332wglQueryPbufferARB(HPBUFFERARB hPbuffer,333int iAttribute,334int *piValue)335{336struct stw_framebuffer *fb;337338if (!hPbuffer) {339SetLastError(ERROR_INVALID_HANDLE);340return FALSE;341}342343fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);344345switch (iAttribute) {346case WGL_PBUFFER_WIDTH_ARB:347*piValue = fb->width;348return TRUE;349case WGL_PBUFFER_HEIGHT_ARB:350*piValue = fb->height;351return TRUE;352case WGL_PBUFFER_LOST_ARB:353/* We assume that no content is ever lost due to display mode change */354*piValue = FALSE;355return TRUE;356/* WGL_ARB_render_texture */357case WGL_TEXTURE_TARGET_ARB:358*piValue = fb->textureTarget;359return TRUE;360case WGL_TEXTURE_FORMAT_ARB:361*piValue = fb->textureFormat;362return TRUE;363case WGL_MIPMAP_TEXTURE_ARB:364*piValue = fb->textureMipmap;365return TRUE;366case WGL_MIPMAP_LEVEL_ARB:367*piValue = fb->textureLevel;368return TRUE;369case WGL_CUBE_MAP_FACE_ARB:370*piValue = fb->textureFace + WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;371return TRUE;372default:373SetLastError(ERROR_INVALID_DATA);374return FALSE;375}376}377378379