mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 994081 - [3/3] Optimize surfaces on Cairo X11, r=Bas f=karlt
This commit is contained in:
parent
82821675ed
commit
19d86c1d8f
@ -11,6 +11,7 @@
|
||||
#include "ScaledFontBase.h"
|
||||
#include "BorrowedContext.h"
|
||||
#include "FilterNodeSoftware.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "cairo-tee.h"
|
||||
@ -27,6 +28,7 @@
|
||||
|
||||
#ifdef CAIRO_HAS_XLIB_SURFACE
|
||||
#include "cairo-xlib.h"
|
||||
#include "cairo-xlib-xrender.h"
|
||||
#endif
|
||||
|
||||
#ifdef CAIRO_HAS_WIN32_SURFACE
|
||||
@ -36,6 +38,9 @@
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCairoSurface, cairo_surface_t, cairo_surface_destroy);
|
||||
|
||||
namespace gfx {
|
||||
|
||||
cairo_surface_t *DrawTargetCairo::mDummySurface;
|
||||
@ -1057,9 +1062,106 @@ DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
return source_surf;
|
||||
}
|
||||
|
||||
#ifdef CAIRO_HAS_XLIB_SURFACE
|
||||
static cairo_user_data_key_t gDestroyPixmapKey;
|
||||
|
||||
struct DestroyPixmapClosure {
|
||||
DestroyPixmapClosure(Drawable d, Screen *s) : mPixmap(d), mScreen(s) {}
|
||||
~DestroyPixmapClosure() {
|
||||
XFreePixmap(DisplayOfScreen(mScreen), mPixmap);
|
||||
}
|
||||
Drawable mPixmap;
|
||||
Screen *mScreen;
|
||||
};
|
||||
|
||||
static void
|
||||
DestroyPixmap(void *data)
|
||||
{
|
||||
delete static_cast<DestroyPixmapClosure*>(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
DrawTargetCairo::OptimizeSourceSurface(SourceSurface *aSurface) const
|
||||
{
|
||||
#ifdef CAIRO_HAS_XLIB_SURFACE
|
||||
if (cairo_surface_get_type(mSurface) != CAIRO_SURFACE_TYPE_XLIB) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
IntSize size = aSurface->GetSize();
|
||||
if (!size.width || !size.height) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
// Although the dimension parameters in the xCreatePixmapReq wire protocol are
|
||||
// 16-bit unsigned integers, the server's CreatePixmap returns BadAlloc if
|
||||
// either dimension cannot be represented by a 16-bit *signed* integer.
|
||||
#define XLIB_IMAGE_SIDE_SIZE_LIMIT 0x7fff
|
||||
|
||||
if (size.width > XLIB_IMAGE_SIDE_SIZE_LIMIT ||
|
||||
size.height > XLIB_IMAGE_SIDE_SIZE_LIMIT) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
SurfaceFormat format = aSurface->GetFormat();
|
||||
Screen *screen = cairo_xlib_surface_get_screen(mSurface);
|
||||
Display *dpy = DisplayOfScreen(screen);
|
||||
XRenderPictFormat* xrenderFormat = nullptr;
|
||||
switch (format) {
|
||||
case SurfaceFormat::B8G8R8A8:
|
||||
xrenderFormat = XRenderFindStandardFormat(dpy, PictStandardARGB32);
|
||||
break;
|
||||
case SurfaceFormat::B8G8R8X8:
|
||||
xrenderFormat = XRenderFindStandardFormat(dpy, PictStandardRGB24);
|
||||
break;
|
||||
case SurfaceFormat::A8:
|
||||
xrenderFormat = XRenderFindStandardFormat(dpy, PictStandardA8);
|
||||
break;
|
||||
default:
|
||||
return aSurface;
|
||||
}
|
||||
if (!xrenderFormat) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
Drawable pixmap = XCreatePixmap(dpy, RootWindowOfScreen(screen),
|
||||
size.width, size.height,
|
||||
xrenderFormat->depth);
|
||||
if (!pixmap) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
ScopedDeletePtr<DestroyPixmapClosure> closure(
|
||||
new DestroyPixmapClosure(pixmap, screen));
|
||||
|
||||
ScopedCairoSurface csurf(
|
||||
cairo_xlib_surface_create_with_xrender_format(dpy, pixmap,
|
||||
screen, xrenderFormat,
|
||||
size.width, size.height));
|
||||
if (!csurf || cairo_surface_status(csurf)) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
cairo_surface_set_user_data(csurf, &gDestroyPixmapKey,
|
||||
closure.forget(), DestroyPixmap);
|
||||
|
||||
RefPtr<DrawTargetCairo> dt = new DrawTargetCairo();
|
||||
if (!dt->Init(csurf, size, &format)) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
dt->CopySurface(aSurface,
|
||||
IntRect(0, 0, size.width, size.height),
|
||||
IntPoint(0, 0));
|
||||
dt->Flush();
|
||||
|
||||
RefPtr<SourceSurface> surf =
|
||||
new SourceSurfaceCairo(csurf, size, format);
|
||||
|
||||
return surf;
|
||||
#endif
|
||||
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user