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; }
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; }
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; }
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; }
/** * 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; }
/** * 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; }
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; }
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; }