svga: fix constant indices for texcoord scale factors and texture buffer size
[mesa.git] / src / gallium / state_trackers / wgl / stw_ext_pbuffer.c
index 32636c603dc2f41a053fd9608477c0a9ed8583e0..d709faa60f24e2a1b70f77ee56f0989df67e49cb 100644 (file)
 #include "pipe/p_defines.h"
 #include "pipe/p_screen.h"
 
+#include "util/u_debug.h"
+
 #include "stw_device.h"
 #include "stw_pixelformat.h"
 #include "stw_framebuffer.h"
 
 
+#define LARGE_WINDOW_SIZE 60000
+
+
+static LRESULT CALLBACK
+WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    MINMAXINFO *pMMI;
+    switch (uMsg) {
+    case WM_GETMINMAXINFO:
+        // Allow to create a window bigger than the desktop
+        pMMI = (MINMAXINFO *)lParam;
+        pMMI->ptMaxSize.x = LARGE_WINDOW_SIZE;
+        pMMI->ptMaxSize.y = LARGE_WINDOW_SIZE;
+        pMMI->ptMaxTrackSize.x = LARGE_WINDOW_SIZE;
+        pMMI->ptMaxTrackSize.y = LARGE_WINDOW_SIZE;
+        break;
+    default:
+        break;
+    }
+
+    return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
 HPBUFFERARB WINAPI
-wglCreatePbufferARB(HDC _hDC,
+wglCreatePbufferARB(HDC hCurrentDC,
                     int iPixelFormat,
                     int iWidth,
                     int iHeight,
@@ -52,10 +78,19 @@ wglCreatePbufferARB(HDC _hDC,
    int useLargest = 0;
    const struct stw_pixelformat_info *info;
    struct stw_framebuffer *fb;
+   DWORD dwExStyle;
+   DWORD dwStyle;
+   RECT rect;
    HWND hWnd;
    HDC hDC;
-
-   info = stw_pixelformat_get_info(iPixelFormat);
+   int iDisplayablePixelFormat;
+   PIXELFORMATDESCRIPTOR pfd;
+   BOOL bRet;
+   int textureFormat = WGL_NO_TEXTURE_ARB;
+   int textureTarget = WGL_NO_TEXTURE_ARB;
+   BOOL textureMipmap = FALSE;
+
+   info = stw_pixelformat_get_info(iPixelFormat - 1);
    if (!info) {
       SetLastError(ERROR_INVALID_PIXEL_FORMAT);
       return 0;
@@ -72,8 +107,38 @@ wglCreatePbufferARB(HDC _hDC,
          piAttrib++;
          useLargest = *piAttrib;
          break;
+       case WGL_TEXTURE_FORMAT_ARB:
+          /* WGL_ARB_render_texture */
+          piAttrib++;
+          textureFormat = *piAttrib;
+          if (textureFormat != WGL_TEXTURE_RGB_ARB &&
+             textureFormat != WGL_TEXTURE_RGBA_ARB &&
+             textureFormat != WGL_NO_TEXTURE_ARB) {
+             SetLastError(ERROR_INVALID_DATA);
+             return 0;
+          }
+          break;
+       case WGL_TEXTURE_TARGET_ARB:
+          /* WGL_ARB_render_texture */
+          piAttrib++;
+          textureTarget = *piAttrib;
+          if (textureTarget != WGL_TEXTURE_CUBE_MAP_ARB &&
+              textureTarget != WGL_TEXTURE_1D_ARB &&
+              textureTarget != WGL_TEXTURE_2D_ARB &&
+              textureTarget != WGL_NO_TEXTURE_ARB) {
+             SetLastError(ERROR_INVALID_DATA);
+             return 0;
+          }
+          break;
+      case WGL_MIPMAP_TEXTURE_ARB:
+         /* WGL_ARB_render_texture */
+         piAttrib++;
+         textureMipmap = !!*piAttrib;
+         break;
       default:
          SetLastError(ERROR_INVALID_DATA);
+         debug_printf("wgl: Unsupported attribute 0x%x in %s\n",
+                      *piAttrib, __func__);
          return 0;
       }
    }
@@ -106,22 +171,52 @@ wglCreatePbufferARB(HDC _hDC,
       wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
       wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
-      wc.lpfnWndProc = DefWindowProc;
+      wc.lpfnWndProc = WndProc;
       wc.lpszClassName = "wglpbuffer";
       wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
       RegisterClass(&wc);
       first = FALSE;
    }
 
-   hWnd = CreateWindowEx(0,
+   dwExStyle = 0;
+   dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+   if (0) {
+      /*
+       * Don't hide the window -- useful for debugging what the application is
+       * drawing
+       */
+
+      dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW;
+   } else {
+      dwStyle |= WS_POPUPWINDOW;
+   }
+
+   rect.left = 0;
+   rect.top = 0;
+   rect.right = rect.left + iWidth;
+   rect.bottom = rect.top + iHeight;
+
+   /*
+    * The CreateWindowEx parameters are the total (outside) dimensions of the
+    * window, which can vary with Windows version and user settings.  Use
+    * AdjustWindowRect to get the required total area for the given client area.
+    *
+    * AdjustWindowRectEx does not accept WS_OVERLAPPED style (which is defined
+    * as 0), which means we need to use some other style instead, e.g.,
+    * WS_OVERLAPPEDWINDOW or WS_POPUPWINDOW as above.
+    */
+
+   AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
+
+   hWnd = CreateWindowEx(dwExStyle,
                          "wglpbuffer", /* wc.lpszClassName */
-                         "wglpbuffer",
-#if 0 /* Useful for debugging what the application is drawing */
-                         WS_VISIBLE |
-#endif
-                         WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
-                         CW_USEDEFAULT, CW_USEDEFAULT, /* x, y */
-                         iWidth, iHeight,
+                         NULL,
+                         dwStyle,
+                         CW_USEDEFAULT, /* x */
+                         CW_USEDEFAULT, /* y */
+                         rect.right - rect.left, /* width */
+                         rect.bottom - rect.top, /* height */
                          NULL,
                          NULL,
                          NULL,
@@ -130,18 +225,51 @@ wglCreatePbufferARB(HDC _hDC,
       return 0;
    }
 
+#ifdef DEBUG
+   /*
+    * Verify the client area size matches the specified size.
+    */
+
+   GetClientRect(hWnd, &rect);
+   assert(rect.left == 0);
+   assert(rect.top == 0);
+   assert(rect.right - rect.left == iWidth);
+   assert(rect.bottom - rect.top == iHeight);
+#endif
+
    hDC = GetDC(hWnd);
    if (!hDC) {
       return 0;
    }
 
-   SetPixelFormat(hDC, iPixelFormat, &info->pfd);
-
+   /*
+    * We can't pass non-displayable pixel formats to GDI, which is why we
+    * create the framebuffer object before calling SetPixelFormat().
+    */
    fb = stw_framebuffer_create(hDC, iPixelFormat);
    if (!fb) {
       SetLastError(ERROR_NO_SYSTEM_RESOURCES);
+      return NULL;
    }
 
+   fb->bPbuffer = TRUE;
+
+   /* WGL_ARB_render_texture fields */
+   fb->textureTarget = textureTarget;
+   fb->textureFormat = textureFormat;
+   fb->textureMipmap = textureMipmap;
+
+   iDisplayablePixelFormat = fb->iDisplayablePixelFormat;
+
+   stw_framebuffer_unlock(fb);
+
+   /*
+    * We need to set a displayable pixel format on the hidden window DC
+    * so that wglCreateContext and wglMakeCurrent are not overruled by GDI.
+    */
+   bRet = SetPixelFormat(hDC, iDisplayablePixelFormat, &pfd);
+   assert(bRet);
+
    return (HPBUFFERARB)fb;
 }
 
@@ -152,10 +280,14 @@ wglGetPbufferDCARB(HPBUFFERARB hPbuffer)
    struct stw_framebuffer *fb;
    HDC hDC;
 
-   fb = (struct stw_framebuffer *)hPbuffer;
+   if (!hPbuffer) {
+      SetLastError(ERROR_INVALID_HANDLE);
+      return NULL;
+   }
+
+   fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);
 
    hDC = GetDC(fb->hWnd);
-   SetPixelFormat(hDC, fb->iPixelFormat, &fb->pfi->pfd);
 
    return hDC;
 }
@@ -167,7 +299,12 @@ wglReleasePbufferDCARB(HPBUFFERARB hPbuffer,
 {
    struct stw_framebuffer *fb;
 
-   fb = (struct stw_framebuffer *)hPbuffer;
+   if (!hPbuffer) {
+      SetLastError(ERROR_INVALID_HANDLE);
+      return 0;
+   }
+
+   fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);
 
    return ReleaseDC(fb->hWnd, hDC);
 }
@@ -178,7 +315,12 @@ wglDestroyPbufferARB(HPBUFFERARB hPbuffer)
 {
    struct stw_framebuffer *fb;
 
-   fb = (struct stw_framebuffer *)hPbuffer;
+   if (!hPbuffer) {
+      SetLastError(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
+
+   fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);
 
    /* This will destroy all our data */
    return DestroyWindow(fb->hWnd);
@@ -192,19 +334,40 @@ wglQueryPbufferARB(HPBUFFERARB hPbuffer,
 {
    struct stw_framebuffer *fb;
 
-   fb = (struct stw_framebuffer *)hPbuffer;
+   if (!hPbuffer) {
+      SetLastError(ERROR_INVALID_HANDLE);
+      return FALSE;
+   }
+
+   fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);
 
    switch (iAttribute) {
    case WGL_PBUFFER_WIDTH_ARB:
       *piValue = fb->width;
       return TRUE;
    case WGL_PBUFFER_HEIGHT_ARB:
-      *piValue = fb->width;
+      *piValue = fb->height;
       return TRUE;
    case WGL_PBUFFER_LOST_ARB:
       /* We assume that no content is ever lost due to display mode change */
       *piValue = FALSE;
       return TRUE;
+   /* WGL_ARB_render_texture */
+   case WGL_TEXTURE_TARGET_ARB:
+      *piValue = fb->textureTarget;
+      return TRUE;
+   case WGL_TEXTURE_FORMAT_ARB:
+      *piValue = fb->textureFormat;
+      return TRUE;
+   case WGL_MIPMAP_TEXTURE_ARB:
+      *piValue = fb->textureMipmap;
+      return TRUE;
+   case WGL_MIPMAP_LEVEL_ARB:
+      *piValue = fb->textureLevel;
+      return TRUE;
+   case WGL_CUBE_MAP_FACE_ARB:
+      *piValue = fb->textureFace + WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
+      return TRUE;
    default:
       SetLastError(ERROR_INVALID_DATA);
       return FALSE;