forked from Mirrors/wine-wine
winex11: Use window surfaces for rendering top-level windows.
It can be disabled by setting "ClientSideGraphics"="n".oldstable
parent
7304445a7e
commit
33ac850c80
|
@ -918,6 +918,17 @@ static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse )
|
|||
return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] );
|
||||
}
|
||||
|
||||
static inline int get_dib_stride( int width, int bpp )
|
||||
{
|
||||
return ((width * bpp + 31) >> 3) & ~3;
|
||||
}
|
||||
|
||||
static inline int get_dib_image_size( const BITMAPINFO *info )
|
||||
{
|
||||
return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount )
|
||||
* abs( info->bmiHeader.biHeight );
|
||||
}
|
||||
|
||||
/* store the palette or color mask data in the bitmap info structure */
|
||||
static void set_color_info( const XVisualInfo *vis, BITMAPINFO *info )
|
||||
{
|
||||
|
@ -1517,3 +1528,184 @@ DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo
|
|||
XDestroyImage( image );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct x11drv_window_surface
|
||||
{
|
||||
struct window_surface header;
|
||||
Window window;
|
||||
GC gc;
|
||||
XImage *image;
|
||||
RECT bounds;
|
||||
BOOL is_r8g8b8;
|
||||
struct gdi_image_bits bits;
|
||||
CRITICAL_SECTION crit;
|
||||
BITMAPINFO info; /* variable size, must be last */
|
||||
};
|
||||
|
||||
static struct x11drv_window_surface *get_x11_surface( struct window_surface *surface )
|
||||
{
|
||||
return (struct x11drv_window_surface *)surface;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* x11drv_surface_lock
|
||||
*/
|
||||
static void x11drv_surface_lock( struct window_surface *window_surface )
|
||||
{
|
||||
struct x11drv_window_surface *surface = get_x11_surface( window_surface );
|
||||
|
||||
EnterCriticalSection( &surface->crit );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* x11drv_surface_unlock
|
||||
*/
|
||||
static void x11drv_surface_unlock( struct window_surface *window_surface )
|
||||
{
|
||||
struct x11drv_window_surface *surface = get_x11_surface( window_surface );
|
||||
|
||||
LeaveCriticalSection( &surface->crit );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* x11drv_surface_get_bitmap_info
|
||||
*/
|
||||
static void *x11drv_surface_get_bitmap_info( struct window_surface *window_surface, BITMAPINFO *info )
|
||||
{
|
||||
struct x11drv_window_surface *surface = get_x11_surface( window_surface );
|
||||
|
||||
memcpy( info, &surface->info, get_dib_info_size( &surface->info, DIB_RGB_COLORS ));
|
||||
return surface->bits.ptr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* x11drv_surface_get_bounds
|
||||
*/
|
||||
static RECT *x11drv_surface_get_bounds( struct window_surface *window_surface )
|
||||
{
|
||||
struct x11drv_window_surface *surface = get_x11_surface( window_surface );
|
||||
|
||||
return &surface->bounds;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* x11drv_surface_flush
|
||||
*/
|
||||
static void x11drv_surface_flush( struct window_surface *window_surface )
|
||||
{
|
||||
struct x11drv_window_surface *surface = get_x11_surface( window_surface );
|
||||
struct bitblt_coords coords;
|
||||
struct gdi_image_bits dst_bits;
|
||||
const int *mapping = NULL;
|
||||
|
||||
window_surface->funcs->lock( window_surface );
|
||||
coords.x = 0;
|
||||
coords.y = 0;
|
||||
coords.width = surface->header.rect.right - surface->header.rect.left;
|
||||
coords.height = surface->header.rect.bottom - surface->header.rect.top;
|
||||
SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
|
||||
if (IntersectRect( &coords.visrect, &coords.visrect, &surface->bounds ))
|
||||
{
|
||||
TRACE( "flushing %p %dx%d bounds %s bits %p\n",
|
||||
surface, coords.width, coords.height,
|
||||
wine_dbgstr_rect( &surface->bounds ), surface->bits.ptr );
|
||||
|
||||
if (surface->image->bits_per_pixel == 4 || surface->image->bits_per_pixel == 8)
|
||||
mapping = X11DRV_PALETTE_PaletteToXPixel;
|
||||
|
||||
if (!copy_image_bits( &surface->info, surface->is_r8g8b8, surface->image,
|
||||
&surface->bits, &dst_bits, &coords, mapping, ~0u ))
|
||||
{
|
||||
surface->image->data = dst_bits.ptr;
|
||||
XPutImage( gdi_display, surface->window, surface->gc, surface->image,
|
||||
coords.visrect.left, 0,
|
||||
surface->header.rect.left + coords.visrect.left,
|
||||
surface->header.rect.top + coords.visrect.top,
|
||||
coords.visrect.right - coords.visrect.left,
|
||||
coords.visrect.bottom - coords.visrect.top );
|
||||
surface->image->data = NULL;
|
||||
}
|
||||
|
||||
if (dst_bits.free) dst_bits.free( &dst_bits );
|
||||
}
|
||||
reset_bounds( &surface->bounds );
|
||||
window_surface->funcs->unlock( window_surface );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* x11drv_surface_destroy
|
||||
*/
|
||||
static void x11drv_surface_destroy( struct window_surface *window_surface )
|
||||
{
|
||||
struct x11drv_window_surface *surface = get_x11_surface( window_surface );
|
||||
|
||||
TRACE( "freeing %p bits %p\n", surface, surface->bits.ptr );
|
||||
if (surface->gc) XFreeGC( gdi_display, surface->gc );
|
||||
if (surface->image) XDestroyImage( surface->image );
|
||||
if (surface->bits.free) surface->bits.free( &surface->bits );
|
||||
surface->crit.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection( &surface->crit );
|
||||
HeapFree( GetProcessHeap(), 0, surface );
|
||||
}
|
||||
|
||||
static const struct window_surface_funcs x11drv_surface_funcs =
|
||||
{
|
||||
x11drv_surface_lock,
|
||||
x11drv_surface_unlock,
|
||||
x11drv_surface_get_bitmap_info,
|
||||
x11drv_surface_get_bounds,
|
||||
x11drv_surface_flush,
|
||||
x11drv_surface_destroy
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* create_surface
|
||||
*/
|
||||
struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect )
|
||||
{
|
||||
const XPixmapFormatValues *format = pixmap_formats[vis->depth];
|
||||
struct x11drv_window_surface *surface;
|
||||
int width = rect->right - rect->left, height = rect->bottom - rect->top;
|
||||
int colors = format->bits_per_pixel <= 8 ? 1 << format->bits_per_pixel : 3;
|
||||
|
||||
surface = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] ));
|
||||
if (!surface) return NULL;
|
||||
surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader);
|
||||
surface->info.bmiHeader.biWidth = width;
|
||||
surface->info.bmiHeader.biHeight = -height; /* top-down */
|
||||
surface->info.bmiHeader.biPlanes = 1;
|
||||
surface->info.bmiHeader.biBitCount = format->bits_per_pixel;
|
||||
surface->info.bmiHeader.biSizeImage = get_dib_image_size( &surface->info );
|
||||
set_color_info( vis, &surface->info );
|
||||
|
||||
InitializeCriticalSection( &surface->crit );
|
||||
surface->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface");
|
||||
|
||||
surface->header.funcs = &x11drv_surface_funcs;
|
||||
surface->header.rect = *rect;
|
||||
surface->header.ref = 1;
|
||||
surface->window = window;
|
||||
surface->is_r8g8b8 = is_r8g8b8( vis );
|
||||
reset_bounds( &surface->bounds );
|
||||
if (!(surface->bits.ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
surface->info.bmiHeader.biSizeImage )))
|
||||
goto failed;
|
||||
|
||||
surface->bits.free = free_heap_bits;
|
||||
|
||||
surface->image = XCreateImage( gdi_display, visual, vis->depth, ZPixmap, 0, NULL,
|
||||
width, height, 32, 0 );
|
||||
if (!surface->image) goto failed;
|
||||
surface->gc = XCreateGC( gdi_display, window, 0, NULL );
|
||||
|
||||
TRACE( "created %p for %lx %s bits %p-%p\n", surface, window, wine_dbgstr_rect(rect),
|
||||
surface->bits.ptr, (char *)surface->bits.ptr + surface->info.bmiHeader.biSizeImage );
|
||||
|
||||
return &surface->header;
|
||||
|
||||
failed:
|
||||
x11drv_surface_destroy( &surface->header );
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1462,6 +1462,8 @@ static void destroy_whole_window( Display *display, struct x11drv_win_data *data
|
|||
XFlush( display );
|
||||
XFree( data->wm_hints );
|
||||
data->wm_hints = NULL;
|
||||
if (data->surface) window_surface_release( data->surface );
|
||||
data->surface = NULL;
|
||||
RemovePropA( data->hwnd, whole_window_prop );
|
||||
}
|
||||
|
||||
|
@ -2006,6 +2008,20 @@ void CDECL X11DRV_SetFocus( HWND hwnd )
|
|||
}
|
||||
|
||||
|
||||
static inline RECT get_surface_rect( const RECT *visible_rect )
|
||||
{
|
||||
RECT rect;
|
||||
|
||||
IntersectRect( &rect, visible_rect, &virtual_screen_rect );
|
||||
OffsetRect( &rect, -visible_rect->left, -visible_rect->top );
|
||||
rect.left &= ~31;
|
||||
rect.top &= ~31;
|
||||
rect.right = max( rect.left + 32, (rect.right + 31) & ~31 );
|
||||
rect.bottom = max( rect.top + 32, (rect.bottom + 31) & ~31 );
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WindowPosChanging (X11DRV.@)
|
||||
*/
|
||||
|
@ -2014,6 +2030,8 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag
|
|||
struct window_surface **surface )
|
||||
{
|
||||
struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
|
||||
RECT surface_rect;
|
||||
XVisualInfo vis;
|
||||
|
||||
if (!data && !(data = X11DRV_create_win_data( hwnd, window_rect, client_rect ))) return;
|
||||
|
||||
|
@ -2028,6 +2046,34 @@ void CDECL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flag
|
|||
|
||||
*visible_rect = *window_rect;
|
||||
X11DRV_window_to_X_rect( data, visible_rect );
|
||||
|
||||
/* create the window surface if necessary */
|
||||
if (!data->whole_window) return;
|
||||
if (swp_flags & SWP_HIDEWINDOW) return;
|
||||
if (data->whole_window == root_window) return;
|
||||
if (!client_side_graphics) return;
|
||||
|
||||
surface_rect = get_surface_rect( visible_rect );
|
||||
if (data->surface)
|
||||
{
|
||||
if (!memcmp( &data->surface->rect, &surface_rect, sizeof(surface_rect) ))
|
||||
{
|
||||
/* existing surface is good enough */
|
||||
window_surface_add_ref( data->surface );
|
||||
*surface = data->surface;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!(swp_flags & SWP_SHOWWINDOW) && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return;
|
||||
|
||||
memset( &vis, 0, sizeof(vis) );
|
||||
vis.visual = visual;
|
||||
vis.visualid = visual->visualid;
|
||||
vis.depth = screen_depth;
|
||||
vis.red_mask = visual->red_mask;
|
||||
vis.green_mask = visual->green_mask;
|
||||
vis.blue_mask = visual->blue_mask;
|
||||
*surface = create_surface( data->whole_window, &vis, &surface_rect );
|
||||
}
|
||||
|
||||
|
||||
|
@ -2057,6 +2103,9 @@ void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags
|
|||
data->window_rect = *rectWindow;
|
||||
data->whole_rect = *visible_rect;
|
||||
data->client_rect = *rectClient;
|
||||
if (surface) window_surface_add_ref( surface );
|
||||
if (data->surface) window_surface_release( data->surface );
|
||||
data->surface = surface;
|
||||
|
||||
TRACE( "win %p window %s client %s style %08x flags %08x\n",
|
||||
hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style, swp_flags );
|
||||
|
|
|
@ -190,6 +190,7 @@ extern Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const B
|
|||
const struct gdi_image_bits *bits, UINT coloruse ) DECLSPEC_HIDDEN;
|
||||
extern DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis,
|
||||
BITMAPINFO *info, struct gdi_image_bits *bits ) DECLSPEC_HIDDEN;
|
||||
extern struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) DECLSPEC_HIDDEN;
|
||||
extern BOOL add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) DECLSPEC_HIDDEN;
|
||||
|
@ -205,6 +206,7 @@ extern INT X11DRV_YWStoDS( HDC hdc, INT height ) DECLSPEC_HIDDEN;
|
|||
|
||||
extern const int X11DRV_XROPfunction[];
|
||||
|
||||
extern int client_side_graphics DECLSPEC_HIDDEN;
|
||||
extern int client_side_with_render DECLSPEC_HIDDEN;
|
||||
extern int client_side_antialias_with_core DECLSPEC_HIDDEN;
|
||||
extern int client_side_antialias_with_render DECLSPEC_HIDDEN;
|
||||
|
@ -546,6 +548,7 @@ struct x11drv_win_data
|
|||
DWORD net_wm_state; /* bit mask of active x11drv_net_wm_state values */
|
||||
Window embedder; /* window id of embedder */
|
||||
unsigned long configure_serial; /* serial number of last configure request */
|
||||
struct window_surface *surface;
|
||||
Pixmap icon_pixmap;
|
||||
Pixmap icon_mask;
|
||||
};
|
||||
|
|
|
@ -79,6 +79,7 @@ int managed_mode = 1;
|
|||
int decorated_mode = 1;
|
||||
int private_color_map = 0;
|
||||
int primary_monitor = 0;
|
||||
int client_side_graphics = 1;
|
||||
int client_side_with_render = 1;
|
||||
int client_side_antialias_with_core = 1;
|
||||
int client_side_antialias_with_render = 1;
|
||||
|
@ -389,6 +390,9 @@ static void setup_options(void)
|
|||
if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
|
||||
screen_depth = atoi(buffer);
|
||||
|
||||
if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
|
||||
client_side_graphics = IS_OPTION_TRUE( buffer[0] );
|
||||
|
||||
if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
|
||||
client_side_with_render = IS_OPTION_TRUE( buffer[0] );
|
||||
|
||||
|
|
Loading…
Reference in New Issue