LONG APIENTRY
DrvDescribePixelFormat(
   HDC hdc,
   INT iPixelFormat,
   ULONG cjpfd,
   PIXELFORMATDESCRIPTOR *ppfd )
{
   uint count;
   uint index;
   const struct stw_pixelformat_info *pfi;

   (void) hdc;

   if (!stw_dev)
      return 0;

   count = stw_pixelformat_get_extended_count();
   index = (uint) iPixelFormat - 1;

   if (ppfd == NULL)
      return count;
   if (index >= count || cjpfd != sizeof( PIXELFORMATDESCRIPTOR ))
      return 0;

   pfi = stw_pixelformat_get_info( index );
   
   memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR ));

   return count;
}
Beispiel #2
0
LONG APIENTRY
DrvDescribePixelFormat(
   HDC hdc,
   INT iPixelFormat,
   ULONG cjpfd,
   PIXELFORMATDESCRIPTOR *ppfd )
{
   uint count;
   const struct stw_pixelformat_info *pfi;

   (void) hdc;

   if (!stw_dev)
      return 0;

   count = stw_pixelformat_get_count();

   if (ppfd == NULL)
      return count;
   if (cjpfd != sizeof( PIXELFORMATDESCRIPTOR ))
      return 0;

   pfi = stw_pixelformat_get_info( iPixelFormat );
   if (!pfi) {
      return 0;
   }
   
   memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR ));

   return count;
}
Beispiel #3
0
DHGLRC APIENTRY
DrvCreateLayerContext(
   HDC hdc,
   INT iLayerPlane )
{
   int iPixelFormat;
   const struct stw_pixelformat_info *pfi;
   struct st_context_attribs attribs;
   struct stw_context *ctx = NULL;
   
   if(!stw_dev)
      return 0;
   
   if (iLayerPlane != 0)
      return 0;

   iPixelFormat = GetPixelFormat(hdc);
   if(!iPixelFormat)
      return 0;
   
   pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
   
   ctx = CALLOC_STRUCT( stw_context );
   if (ctx == NULL)
      goto no_ctx;

   ctx->hdc = hdc;
   ctx->iPixelFormat = iPixelFormat;

   memset(&attribs, 0, sizeof(attribs));
   attribs.profile = ST_PROFILE_DEFAULT;
   attribs.visual = pfi->stvis;

   ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
         stw_dev->smapi, &attribs, NULL);
   if (ctx->st == NULL) 
      goto no_st_ctx;

   ctx->st->st_manager_private = (void *) ctx;

   pipe_mutex_lock( stw_dev->ctx_mutex );
   ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx);
   pipe_mutex_unlock( stw_dev->ctx_mutex );
   if (!ctx->dhglrc)
      goto no_hglrc;

   return ctx->dhglrc;

no_hglrc:
   ctx->st->destroy(ctx->st);
no_st_ctx:
   FREE(ctx);
no_ctx:
   return 0;
}
/* Only used by the wgl code, but have it here to avoid exporting the
 * pixelformat.h functionality.
 */
int stw_pixelformat_choose( HDC hdc,
                            CONST PIXELFORMATDESCRIPTOR *ppfd )
{
   uint count;
   uint index;
   uint bestindex;
   uint bestdelta;

   (void) hdc;

   count = stw_pixelformat_get_count();
   bestindex = count;
   bestdelta = ~0U;

   for (index = 0; index < count; index++) {
      uint delta = 0;
      const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info( index );

      if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
          !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
          !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
         continue;

      /* FIXME: Take in account individual channel bits */
      if (ppfd->cColorBits != pfi->pfd.cColorBits)
         delta += 8;

      if (ppfd->cDepthBits != pfi->pfd.cDepthBits)
         delta += 4;

      if (ppfd->cStencilBits != pfi->pfd.cStencilBits)
         delta += 2;

      if (ppfd->cAlphaBits != pfi->pfd.cAlphaBits)
         delta++;

      if (delta < bestdelta) {
         bestindex = index;
         bestdelta = delta;
         if (bestdelta == 0)
            break;
      }
   }

   if (bestindex == count)
      return 0;

   return bestindex + 1;
}
Beispiel #5
0
HPBUFFERARB WINAPI
wglCreatePbufferARB(HDC hCurrentDC,
                    int iPixelFormat,
                    int iWidth,
                    int iHeight,
                    const int *piAttribList)
{
   static boolean first = TRUE;
   const int *piAttrib;
   int useLargest = 0;
   const struct stw_pixelformat_info *info;
   struct stw_framebuffer *fb;
   DWORD dwExStyle;
   DWORD dwStyle;
   RECT rect;
   HWND hWnd;
   HDC hDC;
   int iDisplayablePixelFormat;
   PIXELFORMATDESCRIPTOR pfd;
   BOOL bRet;

   info = stw_pixelformat_get_info(iPixelFormat - 1);
   if (!info) {
      SetLastError(ERROR_INVALID_PIXEL_FORMAT);
      return 0;
   }

   if (iWidth <= 0 || iHeight <= 0) {
      SetLastError(ERROR_INVALID_DATA);
      return 0;
   }

   for (piAttrib = piAttribList; *piAttrib; piAttrib++) {
      switch (*piAttrib) {
      case WGL_PBUFFER_LARGEST_ARB:
         piAttrib++;
         useLargest = *piAttrib;
         break;
      default:
         SetLastError(ERROR_INVALID_DATA);
         return 0;
      }
   }

   if (iWidth > stw_dev->max_2d_length) {
      if (useLargest) {
         iWidth = stw_dev->max_2d_length;
      } else {
         SetLastError(ERROR_NO_SYSTEM_RESOURCES);
         return 0;
      }
   }

   if (iHeight > stw_dev->max_2d_length) {
      if (useLargest) {
         iHeight = stw_dev->max_2d_length;
      } else {
         SetLastError(ERROR_NO_SYSTEM_RESOURCES);
         return 0;
      }
   }

   /*
    * Implement pbuffers through invisible windows
    */

   if (first) {
      WNDCLASS wc;
      memset(&wc, 0, sizeof wc);
      wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
      wc.hCursor = LoadCursor(NULL, IDC_ARROW);
      wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
      wc.lpfnWndProc = WndProc;
      wc.lpszClassName = "wglpbuffer";
      wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
      RegisterClass(&wc);
      first = FALSE;
   }

   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 */
                         NULL,
                         dwStyle,
                         CW_USEDEFAULT, /* x */
                         CW_USEDEFAULT, /* y */
                         rect.right - rect.left, /* width */
                         rect.bottom - rect.top, /* height */
                         NULL,
                         NULL,
                         NULL,
                         NULL);
   if (!hWnd) {
      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;
   }

   /*
    * 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;
   iDisplayablePixelFormat = fb->iDisplayablePixelFormat;

   stw_framebuffer_release(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;
}
Beispiel #6
0
/**
 * Create a new stw_framebuffer object which corresponds to the given
 * HDC/window.  If successful, we return the new stw_framebuffer object
 * with its mutex locked.
 */
struct stw_framebuffer *
stw_framebuffer_create(HDC hdc, int iPixelFormat)
{
   HWND hWnd;
   struct stw_framebuffer *fb;
   const struct stw_pixelformat_info *pfi;

   /* We only support drawing to a window. */
   hWnd = WindowFromDC( hdc );
   if (!hWnd)
      return NULL;

   fb = CALLOC_STRUCT( stw_framebuffer );
   if (fb == NULL)
      return NULL;

   fb->hWnd = hWnd;
   fb->iPixelFormat = iPixelFormat;

   /*
    * We often need a displayable pixel format to make GDI happy. Set it
    * here (always 1, i.e., out first pixel format) where appropriate.
    */
   fb->iDisplayablePixelFormat = iPixelFormat <= stw_dev->pixelformat_count
      ? iPixelFormat : 1;

   fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat );
   fb->stfb = stw_st_create_framebuffer( fb );
   if (!fb->stfb) {
      FREE( fb );
      return NULL;
   }

   fb->refcnt = 1;

   /*
    * Windows can be sometimes have zero width and or height, but we ensure
    * a non-zero framebuffer size at all times.
    */

   fb->must_resize = TRUE;
   fb->width  = 1;
   fb->height = 1;
   fb->client_rect.left   = 0;
   fb->client_rect.top    = 0;
   fb->client_rect.right  = fb->client_rect.left + fb->width;
   fb->client_rect.bottom = fb->client_rect.top  + fb->height;

   stw_framebuffer_get_size(fb);

   InitializeCriticalSection(&fb->mutex);

   /* This is the only case where we lock the stw_framebuffer::mutex before
    * stw_dev::fb_mutex, since no other thread can know about this framebuffer
    * and we must prevent any other thread from destroying it before we return.
    */
   stw_framebuffer_lock(fb);

   stw_lock_framebuffers(stw_dev);
   fb->next = stw_dev->fb_head;
   stw_dev->fb_head = fb;
   stw_unlock_framebuffers(stw_dev);

   return fb;
}
Beispiel #7
0
/**
 * Called via DrvCreateContext(), DrvCreateLayerContext() and
 * wglCreateContextAttribsARB() to actually create a rendering context.
 * \param handle  the desired DHGLRC handle to use for the context, or zero
 *                if a new handle should be allocated.
 * \return the handle for the new context or zero if there was a problem.
 */
DHGLRC
stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext,
                           int majorVersion, int minorVersion,
                           int contextFlags, int profileMask,
                           DHGLRC handle)
{
    int iPixelFormat;
    struct stw_framebuffer *fb;
    const struct stw_pixelformat_info *pfi;
    struct st_context_attribs attribs;
    struct stw_context *ctx = NULL;
    struct stw_context *shareCtx = NULL;
    enum st_context_error ctx_err = 0;

    if (!stw_dev)
        return 0;

    if (iLayerPlane != 0)
        return 0;

    iPixelFormat = GetPixelFormat(hdc);
    if(!iPixelFormat)
        return 0;

    /*
     * GDI only knows about displayable pixel formats, so determine the pixel
     * format from the framebuffer.
     *
     * TODO: Remove the GetPixelFormat() above, and stop relying on GDI.
     */
    fb = stw_framebuffer_from_hdc( hdc );
    if (fb) {
        assert(iPixelFormat == fb->iDisplayablePixelFormat);
        iPixelFormat = fb->iPixelFormat;
        stw_framebuffer_release(fb);
    }

    pfi = stw_pixelformat_get_info( iPixelFormat );

    if (hShareContext != 0) {
        pipe_mutex_lock( stw_dev->ctx_mutex );
        shareCtx = stw_lookup_context_locked( hShareContext );
        pipe_mutex_unlock( stw_dev->ctx_mutex );
    }

    ctx = CALLOC_STRUCT( stw_context );
    if (ctx == NULL)
        goto no_ctx;

    ctx->hdc = hdc;
    ctx->iPixelFormat = iPixelFormat;

    memset(&attribs, 0, sizeof(attribs));
    attribs.visual = pfi->stvis;
    attribs.major = majorVersion;
    attribs.minor = minorVersion;
    if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
        attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
    if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB)
        attribs.flags |= ST_CONTEXT_FLAG_DEBUG;

    switch (profileMask) {
    case WGL_CONTEXT_CORE_PROFILE_BIT_ARB:
        /* There are no profiles before OpenGL 3.2.  The
         * WGL_ARB_create_context_profile spec says:
         *
         *     "If the requested OpenGL version is less than 3.2,
         *     WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
         *     of the context is determined solely by the requested version."
         */
        if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2)) {
            attribs.profile = ST_PROFILE_OPENGL_CORE;
            break;
        }
    /* fall-through */
    case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
        /*
         * The spec also says:
         *
         *     "If version 3.1 is requested, the context returned may implement
         *     any of the following versions:
         *
         *       * Version 3.1. The GL_ARB_compatibility extension may or may not
         *         be implemented, as determined by the implementation.
         *       * The core profile of version 3.2 or greater."
         *
         * and because Mesa doesn't support GL_ARB_compatibility, the only chance to
         * honour a 3.1 context is through core profile.
         */
        if (majorVersion == 3 && minorVersion == 1) {
            attribs.profile = ST_PROFILE_OPENGL_CORE;
        } else {
            attribs.profile = ST_PROFILE_DEFAULT;
        }
        break;
    case WGL_CONTEXT_ES_PROFILE_BIT_EXT:
        if (majorVersion >= 2) {
            attribs.profile = ST_PROFILE_OPENGL_ES2;
        } else {
            attribs.profile = ST_PROFILE_OPENGL_ES1;
        }
        break;
    default:
        assert(0);
        goto no_st_ctx;
    }

    ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
              stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL);
    if (ctx->st == NULL)
        goto no_st_ctx;

    ctx->st->st_manager_private = (void *) ctx;

    if (ctx->st->cso_context) {
        ctx->hud = hud_create(ctx->st->pipe, ctx->st->cso_context);
    }

    pipe_mutex_lock( stw_dev->ctx_mutex );
    if (handle) {
        /* We're replacing the context data for this handle. See the
         * wglCreateContextAttribsARB() function.
         */
        struct stw_context *old_ctx =
            stw_lookup_context_locked((unsigned) handle);
        if (old_ctx) {
            /* free the old context data associated with this handle */
            if (old_ctx->hud) {
                hud_destroy(old_ctx->hud);
            }
            ctx->st->destroy(old_ctx->st);
            FREE(old_ctx);
        }

        /* replace table entry */
        handle_table_set(stw_dev->ctx_table, (unsigned) handle, ctx);
    }
    else {
        /* create new table entry */
        handle = (DHGLRC) handle_table_add(stw_dev->ctx_table, ctx);
    }

    ctx->dhglrc = handle;

    pipe_mutex_unlock( stw_dev->ctx_mutex );
    if (!ctx->dhglrc)
        goto no_hglrc;

    return ctx->dhglrc;

no_hglrc:
    if (ctx->hud) {
        hud_destroy(ctx->hud);
    }
    ctx->st->destroy(ctx->st);
no_st_ctx:
    FREE(ctx);
no_ctx:
    return 0;
}
static boolean
stw_query_attrib(
   int iPixelFormat,
   int iLayerPlane,
   int attrib,
   int *pvalue )
{
   uint count;
   const struct stw_pixelformat_info *pfi;

   count = stw_pixelformat_get_extended_count();

   if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB) {
      *pvalue = (int) count;
      return TRUE;
   }

   pfi = stw_pixelformat_get_info( iPixelFormat );
   if (!pfi) {
      return FALSE;
   }

   switch (attrib) {
   case WGL_DRAW_TO_WINDOW_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? TRUE : FALSE;
      return TRUE;

   case WGL_DRAW_TO_BITMAP_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_BITMAP ? TRUE : FALSE;
      return TRUE;

   case WGL_NEED_PALETTE_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_NEED_PALETTE ? TRUE : FALSE;
      return TRUE;

   case WGL_NEED_SYSTEM_PALETTE_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE;
      return TRUE;

   case WGL_SWAP_METHOD_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_SWAP_COPY ? WGL_SWAP_COPY_ARB : WGL_SWAP_UNDEFINED_ARB;
      return TRUE;

   case WGL_SWAP_LAYER_BUFFERS_ARB:
      *pvalue = FALSE;
      return TRUE;

   case WGL_NUMBER_OVERLAYS_ARB:
      *pvalue = 0;
      return TRUE;

   case WGL_NUMBER_UNDERLAYS_ARB:
      *pvalue = 0;
      return TRUE;
   }

   if (iLayerPlane != 0)
      return FALSE;

   switch (attrib) {
   case WGL_ACCELERATION_ARB:
      *pvalue = WGL_FULL_ACCELERATION_ARB;
      break;

   case WGL_TRANSPARENT_ARB:
      *pvalue = FALSE;
      break;

   case WGL_TRANSPARENT_RED_VALUE_ARB:
   case WGL_TRANSPARENT_GREEN_VALUE_ARB:
   case WGL_TRANSPARENT_BLUE_VALUE_ARB:
   case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
   case WGL_TRANSPARENT_INDEX_VALUE_ARB:
      break;

   case WGL_SHARE_DEPTH_ARB:
   case WGL_SHARE_STENCIL_ARB:
   case WGL_SHARE_ACCUM_ARB:
      *pvalue = TRUE;
      break;

   case WGL_SUPPORT_GDI_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_GDI ? TRUE : FALSE;
      break;

   case WGL_SUPPORT_OPENGL_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_OPENGL ? TRUE : FALSE;
      break;

   case WGL_DOUBLE_BUFFER_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_DOUBLEBUFFER ? TRUE : FALSE;
      break;

   case WGL_STEREO_ARB:
      *pvalue = pfi->pfd.dwFlags & PFD_STEREO ? TRUE : FALSE;
      break;

   case WGL_PIXEL_TYPE_ARB:
      switch (pfi->pfd.iPixelType) {
      case PFD_TYPE_RGBA:
         if (util_format_is_float(pfi->stvis.color_format)) {
            *pvalue = WGL_TYPE_RGBA_FLOAT_ARB;
         }
         else {
            *pvalue = WGL_TYPE_RGBA_ARB;
         }
         break;
      case PFD_TYPE_COLORINDEX:
         *pvalue = WGL_TYPE_COLORINDEX_ARB;
         break;
      default:
         return FALSE;
      }
      break;

   case WGL_COLOR_BITS_ARB:
      *pvalue = pfi->pfd.cColorBits;
      break;

   case WGL_RED_BITS_ARB:
      *pvalue = pfi->pfd.cRedBits;
      break;

   case WGL_RED_SHIFT_ARB:
      *pvalue = pfi->pfd.cRedShift;
      break;

   case WGL_GREEN_BITS_ARB:
      *pvalue = pfi->pfd.cGreenBits;
      break;

   case WGL_GREEN_SHIFT_ARB:
      *pvalue = pfi->pfd.cGreenShift;
      break;

   case WGL_BLUE_BITS_ARB:
      *pvalue = pfi->pfd.cBlueBits;
      break;

   case WGL_BLUE_SHIFT_ARB:
      *pvalue = pfi->pfd.cBlueShift;
      break;

   case WGL_ALPHA_BITS_ARB:
      *pvalue = pfi->pfd.cAlphaBits;
      break;

   case WGL_ALPHA_SHIFT_ARB:
      *pvalue = pfi->pfd.cAlphaShift;
      break;

   case WGL_ACCUM_BITS_ARB:
      *pvalue = pfi->pfd.cAccumBits;
      break;

   case WGL_ACCUM_RED_BITS_ARB:
      *pvalue = pfi->pfd.cAccumRedBits;
      break;

   case WGL_ACCUM_GREEN_BITS_ARB:
      *pvalue = pfi->pfd.cAccumGreenBits;
      break;

   case WGL_ACCUM_BLUE_BITS_ARB:
      *pvalue = pfi->pfd.cAccumBlueBits;
      break;

   case WGL_ACCUM_ALPHA_BITS_ARB:
      *pvalue = pfi->pfd.cAccumAlphaBits;
      break;

   case WGL_DEPTH_BITS_ARB:
      *pvalue = pfi->pfd.cDepthBits;
      break;

   case WGL_STENCIL_BITS_ARB:
      *pvalue = pfi->pfd.cStencilBits;
      break;

   case WGL_AUX_BUFFERS_ARB:
      *pvalue = pfi->pfd.cAuxBuffers;
      break;

   case WGL_SAMPLE_BUFFERS_ARB:
      *pvalue = 1;
      break;

   case WGL_SAMPLES_ARB:
      *pvalue = pfi->stvis.samples;
      break;


   /* WGL_ARB_pbuffer */

   case WGL_MAX_PBUFFER_WIDTH_ARB:
   case WGL_MAX_PBUFFER_HEIGHT_ARB:
      *pvalue = stw_dev->max_2d_length;
      break;

   case WGL_MAX_PBUFFER_PIXELS_ARB:
      *pvalue = stw_dev->max_2d_length * stw_dev->max_2d_length;
      break;

   case WGL_DRAW_TO_PBUFFER_ARB:
      *pvalue = 1;
      break;


   default:
      return FALSE;
   }

   return TRUE;
}
Beispiel #9
0
DHGLRC
stw_create_context_attribs(
   HDC hdc,
   INT iLayerPlane,
   DHGLRC hShareContext,
   int majorVersion, int minorVersion,
   int contextFlags, int profileMask)
{
   int iPixelFormat;
   struct stw_framebuffer *fb;
   const struct stw_pixelformat_info *pfi;
   struct st_context_attribs attribs;
   struct stw_context *ctx = NULL;
   struct stw_context *shareCtx = NULL;
   enum st_context_error ctx_err = 0;

   if (!stw_dev)
      return 0;

   if (iLayerPlane != 0)
      return 0;

   iPixelFormat = GetPixelFormat(hdc);
   if(!iPixelFormat)
      return 0;

   /*
    * GDI only knows about displayable pixel formats, so determine the pixel format
    * from the framebuffer.
    *
    * TODO: Remove the GetPixelFormat() above, and stop relying on GDI.
    */
   fb = stw_framebuffer_from_hdc( hdc );
   if (fb) {
      assert(iPixelFormat == fb->iDisplayablePixelFormat);
      iPixelFormat = fb->iPixelFormat;
      stw_framebuffer_release(fb);
   }

   pfi = stw_pixelformat_get_info( iPixelFormat );

   if (hShareContext != 0) {
      pipe_mutex_lock( stw_dev->ctx_mutex );
      shareCtx = stw_lookup_context_locked( hShareContext );
      pipe_mutex_unlock( stw_dev->ctx_mutex );
   }

   ctx = CALLOC_STRUCT( stw_context );
   if (ctx == NULL)
      goto no_ctx;

   ctx->hdc = hdc;
   ctx->iPixelFormat = iPixelFormat;

   memset(&attribs, 0, sizeof(attribs));
   attribs.visual = pfi->stvis;
   attribs.major = majorVersion;
   attribs.minor = minorVersion;
   if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
      attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
   if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB)
      attribs.flags |= ST_CONTEXT_FLAG_DEBUG;

   /* There are no profiles before OpenGL 3.2.  The
    * WGL_ARB_create_context_profile spec says:
    *
    *     "If the requested OpenGL version is less than 3.2,
    *     WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality of the
    *     context is determined solely by the requested version."
    *
    * The spec also says:
    *
    *     "The default value for WGL_CONTEXT_PROFILE_MASK_ARB is
    *     WGL_CONTEXT_CORE_PROFILE_BIT_ARB."
    */
   attribs.profile = ST_PROFILE_DEFAULT;
   if ((majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2))
       && ((profileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) == 0))
      attribs.profile = ST_PROFILE_OPENGL_CORE;

   ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
         stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL);
   if (ctx->st == NULL)
      goto no_st_ctx;

   ctx->st->st_manager_private = (void *) ctx;

   pipe_mutex_lock( stw_dev->ctx_mutex );
   ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx);
   pipe_mutex_unlock( stw_dev->ctx_mutex );
   if (!ctx->dhglrc)
      goto no_hglrc;

   return ctx->dhglrc;

no_hglrc:
   ctx->st->destroy(ctx->st);
no_st_ctx:
   FREE(ctx);
no_ctx:
   return 0;
}
HPBUFFERARB WINAPI
wglCreatePbufferARB(HDC _hDC,
                    int iPixelFormat,
                    int iWidth,
                    int iHeight,
                    const int *piAttribList)
{
    static boolean first = TRUE;
    const int *piAttrib;
    int useLargest = 0;
    const struct stw_pixelformat_info *info;
    struct stw_framebuffer *fb;
    HWND hWnd;
    HDC hDC;

    info = stw_pixelformat_get_info(iPixelFormat);
    if (!info) {
        SetLastError(ERROR_INVALID_PIXEL_FORMAT);
        return 0;
    }

    if (iWidth <= 0 || iHeight <= 0) {
        SetLastError(ERROR_INVALID_DATA);
        return 0;
    }

    for (piAttrib = piAttribList; *piAttrib; piAttrib++) {
        switch (*piAttrib) {
        case WGL_PBUFFER_LARGEST_ARB:
            piAttrib++;
            useLargest = *piAttrib;
            break;
        default:
            SetLastError(ERROR_INVALID_DATA);
            return 0;
        }
    }

    if (iWidth > stw_dev->max_2d_length) {
        if (useLargest) {
            iWidth = stw_dev->max_2d_length;
        } else {
            SetLastError(ERROR_NO_SYSTEM_RESOURCES);
            return 0;
        }
    }

    if (iHeight > stw_dev->max_2d_length) {
        if (useLargest) {
            iHeight = stw_dev->max_2d_length;
        } else {
            SetLastError(ERROR_NO_SYSTEM_RESOURCES);
            return 0;
        }
    }

    /*
     * Implement pbuffers through invisible windows
     */

    if (first) {
        WNDCLASS wc;
        memset(&wc, 0, sizeof wc);
        wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.lpfnWndProc = DefWindowProc;
        wc.lpszClassName = "wglpbuffer";
        wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
        RegisterClass(&wc);
        first = FALSE;
    }

    hWnd = CreateWindowEx(0,
                          "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,
                          NULL,
                          NULL,
                          NULL);
    if (!hWnd) {
        return 0;
    }

    hDC = GetDC(hWnd);
    if (!hDC) {
        return 0;
    }

    SetPixelFormat(hDC, iPixelFormat, &info->pfd);

    fb = stw_framebuffer_create(hDC, iPixelFormat);
    if (!fb) {
        SetLastError(ERROR_NO_SYSTEM_RESOURCES);
    }

    return (HPBUFFERARB)fb;
}
Beispiel #11
0
struct stw_framebuffer *
stw_framebuffer_create(
   HDC hdc,
   int iPixelFormat )
{
   HWND hWnd;
   struct stw_framebuffer *fb;
   const struct stw_pixelformat_info *pfi;

   /* We only support drawing to a window. */
   hWnd = WindowFromDC( hdc );
   if(!hWnd)
      return NULL;
   
   fb = CALLOC_STRUCT( stw_framebuffer );
   if (fb == NULL)
      return NULL;

   /* Applications use, create, destroy device contexts, so the hdc passed is.  We create our own DC
    * because we need one for single buffered visuals.
    */
   fb->hDC = GetDC(hWnd);

   fb->hWnd = hWnd;
   fb->iPixelFormat = iPixelFormat;

   fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
   fb->stfb = stw_st_create_framebuffer( fb );
   if (!fb->stfb) {
      FREE( fb );
      return NULL;
   }

   fb->refcnt = 1;

   /*
    * Windows can be sometimes have zero width and or height, but we ensure
    * a non-zero framebuffer size at all times.
    */

   fb->must_resize = TRUE;
   fb->width  = 1;
   fb->height = 1;
   fb->client_rect.left   = 0;
   fb->client_rect.top    = 0;
   fb->client_rect.right  = fb->client_rect.left + fb->width;
   fb->client_rect.bottom = fb->client_rect.top  + fb->height;

   stw_framebuffer_get_size(fb);

   pipe_mutex_init( fb->mutex );

   /* This is the only case where we lock the stw_framebuffer::mutex before
    * stw_dev::fb_mutex, since no other thread can know about this framebuffer
    * and we must prevent any other thread from destroying it before we return.
    */
   pipe_mutex_lock( fb->mutex );

   pipe_mutex_lock( stw_dev->fb_mutex );
   fb->next = stw_dev->fb_head;
   stw_dev->fb_head = fb;
   pipe_mutex_unlock( stw_dev->fb_mutex );

   return fb;
}