Skip to content
This repository has been archived by the owner on May 4, 2024. It is now read-only.

Commit

Permalink
fshack: winex11: Resolve fbo for glCopyTexSubImage2D.
Browse files Browse the repository at this point in the history
Based on a patch by Illia Polishchuk <effolkronium@gmail.com> from
ValveSoftware#189

GL_INVALID_OPERATION is generated if: the effective value of GL_SAMPLE_BUFFERS
for the read framebuffer is one.

CW-Bug-Id: #22662
  • Loading branch information
Paul Gofman authored and ivyl committed Feb 15, 2024
1 parent f87a852 commit d2b4c06
Showing 1 changed file with 48 additions and 0 deletions.
48 changes: 48 additions & 0 deletions dlls/winex11.drv/opengl.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ struct wgl_context
POINT setup_for;
GLuint current_draw_fbo, current_read_fbo;
BOOL drawing_to_front;
BOOL fs_hack_needs_resolve;
struct list entry;
};

Expand Down Expand Up @@ -477,11 +478,13 @@ static void (*pglUseProgram)( GLuint program );
static void (*pglViewportIndexedf)( GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h );
static void (*pglViewportIndexedfv)( GLuint index, const GLfloat *v );
static void (*pglGetFramebufferAttachmentParameteriv)( GLenum target, GLenum attachment, GLenum pname, GLint *params );
static void (*pglCopyTexSubImage2D)( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
static void wglBindFramebuffer( GLenum target, GLuint framebuffer );
static void wglBindFramebufferEXT( GLenum target, GLuint framebuffer );
static void wglDrawBuffer( GLenum buffer );
static void wglReadBuffer( GLenum src );
static void wglFramebufferTexture2D( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level );
static void wglCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );

/* check if the extension is present in the list */
static BOOL has_extension( const char *list, const char *ext )
Expand Down Expand Up @@ -663,6 +666,7 @@ static void init_opengl(void)
REDIRECT( glFlush );
REDIRECT( glGetString );
REDIRECT( glReadBuffer );
REDIRECT( glCopyTexSubImage2D );
#undef REDIRECT

pglXGetProcAddressARB = dlsym(opengl_handle, "glXGetProcAddressARB");
Expand Down Expand Up @@ -2533,6 +2537,7 @@ static void fs_hack_setup_context( struct wgl_context *ctx, struct gl_drawable *
gl->has_vertex_program = !ctx->is_core &&
has_extension( glExtensions, "GL_ARB_vertex_program" );
ctx->fs_hack_integer = fs_hack_is_integer();
ctx->fs_hack_needs_resolve = gl->fs_hack_needs_resolve;
gl->fs_hack_context_set_up = TRUE;
}
else
Expand Down Expand Up @@ -2687,6 +2692,49 @@ static void wglReadBuffer( GLenum buffer )
pglReadBuffer( buffer );
}

static BOOL resolve_fs_hack_fbo( GLuint *old_read_fbo )
{
struct wgl_context *ctx = NtCurrentTeb()->glContext;
GLuint old_draw_fbo;
unsigned int cx, cy;
RECT user_rect;
HWND hwnd;

if (!ctx || !ctx->fs_hack || !ctx->fs_hack_needs_resolve) return FALSE;
if (!ctx->fs_hack_needs_resolve) return FALSE;
if (ctx->current_read_fbo != ctx->fs_hack_fbo) return FALSE;
if (!(hwnd = NtUserWindowFromDC( ctx->hdc ))) return FALSE;

NtUserGetClientRect( hwnd, &user_rect );
cx = user_rect.right - user_rect.left;
cy = user_rect.bottom - user_rect.top;

TRACE( "resolving fbo, %ux%u.\n", cx, cy );

opengl_funcs.gl.p_glGetIntegerv( GL_READ_FRAMEBUFFER_BINDING, (GLint *)old_read_fbo );
opengl_funcs.gl.p_glGetIntegerv( GL_READ_FRAMEBUFFER_BINDING, (GLint *)&old_draw_fbo );

pglBindFramebuffer( GL_DRAW_FRAMEBUFFER, ctx->fs_hack_resolve_fbo );
pglBlitFramebuffer( 0, 0, cx, cy, 0, 0, cx, cy, GL_COLOR_BUFFER_BIT, GL_NEAREST );
pglBindFramebuffer( GL_READ_FRAMEBUFFER, ctx->fs_hack_resolve_fbo );
pglBindFramebuffer( GL_DRAW_FRAMEBUFFER, old_draw_fbo );

return TRUE;
}

static void wglCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
{
GLuint old_read_fbo;
BOOL restore;

TRACE( "target %#x, level %d, offset %dx%d, origin %dx%d, size %dx%d.\n",
target, level, xoffset, yoffset, x, y, width, height );

restore = resolve_fs_hack_fbo( &old_read_fbo );
pglCopyTexSubImage2D( target, level, xoffset, yoffset, x, y, width, height );
if (restore) pglBindFramebuffer( GL_READ_FRAMEBUFFER, old_read_fbo );
}

struct fs_hack_gl_state
{
GLuint draw_fbo;
Expand Down

0 comments on commit d2b4c06

Please sign in to comment.