wgl: Use pfi instead of iPixelFormat more often

Also, support config-less contexts, and surface-less contexts.

Acked-by: Daniel Stone <daniels@collabora.com>
Acked-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Acked-by: Sidney Just <justsid@x-plane.com>
Acked-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Tested-by: Yonggang Luo <luoyonggang@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12964>
This commit is contained in:
Jesse Natalie 2021-09-21 15:33:26 -07:00 committed by Marge Bot
parent aeb3147a96
commit 35e9c7e082
10 changed files with 109 additions and 92 deletions

View File

@ -498,7 +498,7 @@ wgl_create_context(_EGLDisplay *disp, _EGLConfig *conf,
wgl_ctx->base.ClientMinorVersion,
flags,
profile_mask,
stw_config->iPixelFormat,
stw_config,
resetStrategy);
if (!wgl_ctx->ctx)
@ -727,7 +727,7 @@ wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1] ?
wgl_conf->stw_config[1] : wgl_conf->stw_config[0];
wgl_surf->fb = stw_framebuffer_create(native_window, stw_conf->iPixelFormat, STW_FRAMEBUFFER_EGL_WINDOW, &wgl_dpy->base);
wgl_surf->fb = stw_framebuffer_create(native_window, stw_conf, STW_FRAMEBUFFER_EGL_WINDOW, &wgl_dpy->base);
if (!wgl_surf->fb) {
free(wgl_surf);
return NULL;
@ -757,7 +757,7 @@ wgl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1] ?
wgl_conf->stw_config[1] : wgl_conf->stw_config[0];
wgl_surf->fb = stw_pbuffer_create(stw_conf->iPixelFormat, wgl_surf->base.Width, wgl_surf->base.Height, &wgl_dpy->base);
wgl_surf->fb = stw_pbuffer_create(stw_conf, wgl_surf->base.Width, wgl_surf->base.Height, &wgl_dpy->base);
if (!wgl_surf->fb) {
free(wgl_surf);
return NULL;

View File

@ -129,9 +129,13 @@ DrvCreateLayerContext(HDC hdc, INT iLayerPlane)
if (!stw_dev)
return 0;
const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info_from_hdc(hdc);
if (!pfi)
return 0;
struct stw_context *ctx = stw_create_context_attribs(hdc, iLayerPlane, NULL, stw_dev->smapi, 1, 0, 0,
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0, WGL_NO_RESET_NOTIFICATION_ARB);
pfi, WGL_NO_RESET_NOTIFICATION_ARB);
if (!ctx)
return 0;
@ -142,26 +146,6 @@ DrvCreateLayerContext(HDC hdc, INT iLayerPlane)
return ret;
}
/**
* Return the stw pixel format that most closely matches the pixel format
* on HDC.
* Used to get a pixel format when SetPixelFormat() hasn't been called before.
*/
static int
get_matching_pixel_format(HDC hdc)
{
int iPixelFormat = GetPixelFormat(hdc);
PIXELFORMATDESCRIPTOR pfd;
if (!iPixelFormat)
return 0;
if (!DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd))
return 0;
return stw_pixelformat_choose(hdc, &pfd);
}
/**
* Called via DrvCreateContext(), DrvCreateLayerContext() and
* wglCreateContextAttribsARB() to actually create a rendering context.
@ -171,9 +155,9 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, struct stw_context *shareCt
struct st_manager *smapi,
int majorVersion, int minorVersion,
int contextFlags, int profileMask,
int iPixelFormat, int resetStrategy)
const struct stw_pixelformat_info *pfi,
int resetStrategy)
{
const struct stw_pixelformat_info *pfi;
struct st_context_attribs attribs;
struct stw_context *ctx = NULL;
enum st_context_error ctx_err = 0;
@ -184,32 +168,6 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, struct stw_context *shareCt
if (iLayerPlane != 0)
return 0;
if (!iPixelFormat) {
/*
* GDI only knows about displayable pixel formats, so determine the pixel
* format from the framebuffer.
*
* This also allows to use a OpenGL DLL / ICD without installing.
*/
struct stw_framebuffer *fb;
fb = stw_framebuffer_from_hdc(hdc);
if (fb) {
iPixelFormat = fb->iPixelFormat;
stw_framebuffer_unlock(fb);
}
else {
/* Applications should call SetPixelFormat before creating a context,
* but not all do, and the opengl32 runtime seems to use a default
* pixel format in some cases, so use that.
*/
iPixelFormat = get_matching_pixel_format(hdc);
if (!iPixelFormat)
return 0;
}
}
pfi = stw_pixelformat_get_info( iPixelFormat );
if (shareCtx != NULL)
shareCtx->shared = TRUE;
@ -219,11 +177,12 @@ stw_create_context_attribs(HDC hdc, INT iLayerPlane, struct stw_context *shareCt
ctx->hDrawDC = hdc;
ctx->hReadDC = hdc;
ctx->iPixelFormat = iPixelFormat;
ctx->pfi = pfi;
ctx->shared = shareCtx != NULL;
memset(&attribs, 0, sizeof(attribs));
attribs.visual = pfi->stvis;
if (pfi)
attribs.visual = pfi->stvis;
attribs.major = majorVersion;
attribs.minor = minorVersion;
if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
@ -500,29 +459,28 @@ stw_make_current(struct stw_framebuffer *fb, struct stw_framebuffer *fbRead, str
}
if (ctx) {
if (!fb || !fbRead)
goto fail;
if (fb->iPixelFormat != ctx->iPixelFormat) {
if (ctx->pfi && fb && fb->pfi != ctx->pfi) {
SetLastError(ERROR_INVALID_PIXEL_FORMAT);
goto fail;
}
if (fbRead->iPixelFormat != ctx->iPixelFormat) {
if (ctx->pfi && fbRead && fbRead->pfi != ctx->pfi) {
SetLastError(ERROR_INVALID_PIXEL_FORMAT);
goto fail;
}
stw_framebuffer_lock(fb);
stw_framebuffer_update(fb);
stw_framebuffer_reference_locked(fb);
stw_framebuffer_unlock(fb);
if (fb) {
stw_framebuffer_lock(fb);
stw_framebuffer_update(fb);
stw_framebuffer_reference_locked(fb);
stw_framebuffer_unlock(fb);
}
stw_framebuffer_lock(fbRead);
if (fbRead != fb) {
if (fbRead && fbRead != fb) {
stw_framebuffer_lock(fbRead);
stw_framebuffer_update(fbRead);
stw_framebuffer_reference_locked(fbRead);
stw_framebuffer_unlock(fbRead);
}
stw_framebuffer_unlock(fbRead);
struct stw_framebuffer *old_fb = ctx->current_framebuffer;
struct stw_framebuffer *old_fbRead = ctx->current_read_framebuffer;
@ -530,7 +488,8 @@ stw_make_current(struct stw_framebuffer *fb, struct stw_framebuffer *fbRead, str
ctx->current_read_framebuffer = fbRead;
ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
fb->stfb, fbRead->stfb);
fb ? fb->stfb : NULL,
fbRead ? fbRead->stfb : NULL);
/* Release the old framebuffers from this context. */
release_old_framebuffers(old_fb, old_fbRead, ctx);
@ -578,9 +537,9 @@ get_unlocked_refd_framebuffer_from_dc(HDC hDC)
* pixel format in some cases, so we must create a framebuffer for
* those here.
*/
int iPixelFormat = get_matching_pixel_format(hDC);
int iPixelFormat = stw_pixelformat_guess(hDC);
if (iPixelFormat)
fb = stw_framebuffer_create(WindowFromDC(hDC), iPixelFormat, STW_FRAMEBUFFER_WGL_WINDOW, stw_dev->smapi);
fb = stw_framebuffer_create(WindowFromDC(hDC), stw_pixelformat_get_info(iPixelFormat), STW_FRAMEBUFFER_WGL_WINDOW, stw_dev->smapi);
if (!fb)
return NULL;
}

View File

@ -41,7 +41,7 @@ struct stw_context
{
struct st_context_iface *st;
DHGLRC dhglrc;
int iPixelFormat;
const struct stw_pixelformat_info *pfi;
HDC hDrawDC;
HDC hReadDC;
BOOL shared;
@ -57,7 +57,8 @@ struct stw_context *stw_create_context_attribs(HDC hdc, INT iLayerPlane,
struct st_manager *smapi,
int majorVersion, int minorVersion,
int contextFlags, int profileMask,
int iPixelFormat, int resetStrategy);
const struct stw_pixelformat_info *pfi,
int resetStrategy);
DHGLRC stw_create_context_handle(struct stw_context *context, DHGLRC handle);

View File

@ -213,10 +213,14 @@ wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList)
struct stw_context *share_stw = stw_lookup_context(share_dhglrc);
const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info_from_hdc(hDC);
if (!pfi)
return 0;
struct stw_context *stw_ctx = stw_create_context_attribs(hDC, layerPlane, share_stw,
stw_dev->smapi,
majorVersion, minorVersion,
contextFlags, profileMask, 0,
contextFlags, profileMask, pfi,
resetStrategy);
if (!stw_ctx) {

View File

@ -66,7 +66,7 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
struct stw_framebuffer *
stw_pbuffer_create(int iPixelFormat, int iWidth, int iHeight, struct st_manager *smapi)
stw_pbuffer_create(const struct stw_pixelformat_info *pfi, int iWidth, int iHeight, struct st_manager *smapi)
{
static boolean first = TRUE;
@ -143,7 +143,7 @@ stw_pbuffer_create(int iPixelFormat, int iWidth, int iHeight, struct st_manager
assert(rect.bottom - rect.top == iHeight);
#endif
return stw_framebuffer_create(hWnd, iPixelFormat, STW_FRAMEBUFFER_PBUFFER, smapi);
return stw_framebuffer_create(hWnd, pfi, STW_FRAMEBUFFER_PBUFFER, smapi);
}
@ -164,8 +164,9 @@ wglCreatePbufferARB(HDC hCurrentDC,
int textureFormat = WGL_NO_TEXTURE_ARB;
int textureTarget = WGL_NO_TEXTURE_ARB;
BOOL textureMipmap = FALSE;
const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(iPixelFormat);
if (!stw_pixelformat_get_info(iPixelFormat)) {
if (!pfi) {
SetLastError(ERROR_INVALID_PIXEL_FORMAT);
return 0;
}
@ -241,7 +242,7 @@ wglCreatePbufferARB(HDC hCurrentDC,
* We can't pass non-displayable pixel formats to GDI, which is why we
* create the framebuffer object before calling SetPixelFormat().
*/
fb = stw_pbuffer_create(iPixelFormat, iWidth, iHeight, stw_dev->smapi);
fb = stw_pbuffer_create(pfi, iWidth, iHeight, stw_dev->smapi);
if (!fb) {
SetLastError(ERROR_NO_SYSTEM_RESOURCES);
return NULL;

View File

@ -107,7 +107,7 @@ wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
struct stw_framebuffer *fb, *old_fb, *old_fbRead;
GLenum texFormat, srcBuffer, target;
boolean retVal;
int pixelFormatSave;
const struct stw_pixelformat_info *pfiSave;
/*
* Implementation notes:
@ -170,10 +170,10 @@ wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
* an error condition. After the stw_make_current() we restore the
* buffer's pixel format.
*/
pixelFormatSave = fb->iPixelFormat;
fb->iPixelFormat = curctx->iPixelFormat;
pfiSave = fb->pfi;
fb->pfi = curctx->pfi;
retVal = stw_make_current(fb, fb, curctx);
fb->iPixelFormat = pixelFormatSave;
fb->pfi = pfiSave;
if (!retVal) {
debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n");
return FALSE;

View File

@ -269,32 +269,30 @@ stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam)
* with its mutex locked.
*/
struct stw_framebuffer *
stw_framebuffer_create(HWND hWnd, int iPixelFormat, enum stw_framebuffer_owner owner,
stw_framebuffer_create(HWND hWnd, const struct stw_pixelformat_info *pfi, enum stw_framebuffer_owner owner,
struct st_manager *smapi)
{
struct stw_framebuffer *fb;
const struct stw_pixelformat_info *pfi;
fb = CALLOC_STRUCT( stw_framebuffer );
if (fb == NULL)
return NULL;
fb->hWnd = hWnd;
fb->iPixelFormat = iPixelFormat;
if (stw_dev->stw_winsys->create_framebuffer)
fb->winsys_framebuffer =
stw_dev->stw_winsys->create_framebuffer(stw_dev->screen, hWnd, iPixelFormat);
stw_dev->stw_winsys->create_framebuffer(stw_dev->screen, hWnd, pfi->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->iDisplayablePixelFormat = pfi->iPixelFormat <= stw_dev->pixelformat_count
? pfi->iPixelFormat : 1;
fb->owner = owner;
fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat );
fb->pfi = pfi;
fb->stfb = stw_st_create_framebuffer( fb, smapi );
if (!fb->stfb) {
FREE( fb );
@ -499,7 +497,9 @@ DrvSetPixelFormat(HDC hdc, LONG iPixelFormat)
return bPbuffer;
}
fb = stw_framebuffer_create(WindowFromDC(hdc), iPixelFormat, STW_FRAMEBUFFER_WGL_WINDOW, stw_dev->smapi);
const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(iPixelFormat);
fb = stw_framebuffer_create(WindowFromDC(hdc), pfi, STW_FRAMEBUFFER_WGL_WINDOW, stw_dev->smapi);
if (!fb) {
return FALSE;
}
@ -528,7 +528,7 @@ stw_pixelformat_get(HDC hdc)
fb = stw_framebuffer_from_hdc(hdc);
if (fb) {
iPixelFormat = fb->iPixelFormat;
iPixelFormat = fb->pfi->iPixelFormat;
stw_framebuffer_unlock(fb);
}

View File

@ -84,7 +84,6 @@ struct stw_framebuffer
HWND hWnd;
int iPixelFormat;
const struct stw_pixelformat_info *pfi;
/* A pixel format that can be used by GDI */
@ -154,11 +153,11 @@ struct stw_framebuffer
* must be called when done
*/
struct stw_framebuffer *
stw_framebuffer_create(HWND hwnd, int iPixelFormat, enum stw_framebuffer_owner owner,
stw_framebuffer_create(HWND hwnd, const struct stw_pixelformat_info *pfi, enum stw_framebuffer_owner owner,
struct st_manager *smapi);
struct stw_framebuffer *
stw_pbuffer_create(int iPixelFormat, int iWidth, int iHeight, struct st_manager *smapi);
stw_pbuffer_create(const struct stw_pixelformat_info *pfi, int iWidth, int iHeight, struct st_manager *smapi);
/**

View File

@ -36,6 +36,7 @@
#include <GL/gl.h>
#include "gldrv.h"
#include "stw_device.h"
#include "stw_framebuffer.h"
#include "stw_pixelformat.h"
#include "stw_tls.h"
#include "stw_winsys.h"
@ -382,6 +383,52 @@ stw_pixelformat_get_info(int iPixelFormat)
index);
}
/**
* Return the stw pixel format that most closely matches the pixel format
* on HDC.
* Used to get a pixel format when SetPixelFormat() hasn't been called before.
*/
int
stw_pixelformat_guess(HDC hdc)
{
int iPixelFormat = GetPixelFormat(hdc);
PIXELFORMATDESCRIPTOR pfd;
if (!iPixelFormat)
return 0;
if (!DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd))
return 0;
return stw_pixelformat_choose(hdc, &pfd);
}
const struct stw_pixelformat_info *
stw_pixelformat_get_info_from_hdc(HDC hdc)
{
/*
* GDI only knows about displayable pixel formats, so determine the pixel
* format from the framebuffer.
*
* This also allows to use a OpenGL DLL / ICD without installing.
*/
struct stw_framebuffer *fb;
fb = stw_framebuffer_from_hdc(hdc);
if (fb) {
const struct stw_pixelformat_info *pfi = fb->pfi;
stw_framebuffer_unlock(fb);
return pfi;
}
/* Applications should call SetPixelFormat before creating a context,
* but not all do, and the opengl32 runtime seems to use a default
* pixel format in some cases, so use that.
*/
int iPixelFormat = stw_pixelformat_guess(hdc);
if (!iPixelFormat)
return 0;
return stw_pixelformat_get_info( iPixelFormat );
}
LONG APIENTRY
DrvDescribePixelFormat(HDC hdc, INT iPixelFormat, ULONG cjpfd,

View File

@ -67,6 +67,12 @@ stw_pixelformat_get_extended_count( HDC hdc );
const struct stw_pixelformat_info *
stw_pixelformat_get_info( int iPixelFormat );
const struct stw_pixelformat_info *
stw_pixelformat_get_info_from_hdc( HDC hdc );
int
stw_pixelformat_guess( HDC );
int
stw_pixelformat_choose( HDC hdc,
CONST PIXELFORMATDESCRIPTOR *ppfd );