diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-20 02:00:04 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-20 02:00:04 +0000 |
commit | e68e62fa169c45bd779bfe890aa4fcdaa24d267d (patch) | |
tree | efdb18adec880e7f780d8cde4e12893d3a20234f /skia | |
parent | 7fe07d0726bad485fa40150aa9f7cecb1318217e (diff) | |
download | chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.zip chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.tar.gz chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.tar.bz2 |
Bitmap transport
This patch reworks bitmap transport on all platforms. Linux and Mac
are switched from serialising bitmaps over the IPC channel to using
shared memory. All platforms gain a shared memory mapping cache on the
host side.
The concept of a TransportDIB (device independent bitmap) is added to
encapsulate most of the platform specifics.
On Linux, we use SysV shared memory. This is because X shared pixmaps,
which predate POSIX SHM, can only use SysV. By using SysV between
renderer and browser, we open up the possibility to map the shared
memory directly from the renderer to the X server.
On Mac, we use POSIX shared memory. However, since this needs
filesystem access and the Mac renderer is sandboxed from the
filesystem, we add two new messages from renderer -> browser:
The first, AllocTransportDIB, synchronously creates a transport DIB in
the browser and passes a handle back to the renderer. The second,
FreeTransportDIB, asynchronously, notifies the browser that it may
close its handle to the shared memory region.
On Mac, the shared memory regions are identified by their inode
numbers on the wire. This means that the browser must keep handles
open to all the allocated shared memory regions (since an inode number
is insufficient to map the region). The alternative design is that the
renderer passes the file descriptor with each paint operation. Since
passing file descriptors is special case in the code, I felt that it
would be best to minimise their use. Creating and freeing transport
DIBs are relatively rare operations relative to paints and scrolls.
On Windows, most of the code remains the same, except that Windows now
uses the mapping cache added in this patch. This allows the browser to
maintain a shared memory mapping for a transport DIB over several
paints. Previously it mapped and unmapped for every operation, causing
lots of TLB and VM churn.
Review URL: http://codereview.chromium.org/21485
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10071 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia')
-rw-r--r-- | skia/ext/bitmap_platform_device_linux.h | 2 | ||||
-rwxr-xr-x | skia/ext/bitmap_platform_device_mac.cc | 32 | ||||
-rw-r--r-- | skia/ext/platform_canvas_linux.cc | 19 | ||||
-rw-r--r-- | skia/ext/platform_canvas_linux.h | 1 | ||||
-rwxr-xr-x | skia/ext/platform_canvas_mac.cc | 35 | ||||
-rwxr-xr-x | skia/ext/platform_canvas_mac.h | 3 |
6 files changed, 76 insertions, 16 deletions
diff --git a/skia/ext/bitmap_platform_device_linux.h b/skia/ext/bitmap_platform_device_linux.h index cfc72e2..d26c50d 100644 --- a/skia/ext/bitmap_platform_device_linux.h +++ b/skia/ext/bitmap_platform_device_linux.h @@ -59,9 +59,9 @@ class BitmapPlatformDeviceLinux : public PlatformDeviceLinux { class BitmapPlatformDeviceLinuxData; public: - /// Static constructor. I don't understand this, it's just a copy of the mac static BitmapPlatformDeviceLinux* Create(int width, int height, bool is_opaque); + // This doesn't take ownership of |data| static BitmapPlatformDeviceLinux* Create(int width, int height, bool is_opaque, uint8_t* data); static BitmapPlatformDeviceLinux* Create(int width, int height, diff --git a/skia/ext/bitmap_platform_device_mac.cc b/skia/ext/bitmap_platform_device_mac.cc index 9b4beb0..a0f0bf1 100755 --- a/skia/ext/bitmap_platform_device_mac.cc +++ b/skia/ext/bitmap_platform_device_mac.cc @@ -168,24 +168,26 @@ BitmapPlatformDeviceMac* BitmapPlatformDeviceMac::Create(CGContextRef context, #endif } - CGColorSpaceRef color_space = - CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - // allocate a bitmap context with 4 components per pixel (BGRA). Apple - // recommends these flags for improved CG performance. - CGContextRef bitmap_context = - CGBitmapContextCreate(data, width, height, 8, width*4, - color_space, - kCGImageAlphaPremultipliedFirst | - kCGBitmapByteOrder32Host); - - // Change the coordinate system to match WebCore's - CGContextTranslateCTM(bitmap_context, 0, height); - CGContextScaleCTM(bitmap_context, 1.0, -1.0); - CGColorSpaceRelease(color_space); + if (!context) { + CGColorSpaceRef color_space = + CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + // allocate a bitmap context with 4 components per pixel (BGRA). Apple + // recommends these flags for improved CG performance. + context = + CGBitmapContextCreate(data, width, height, 8, width*4, + color_space, + kCGImageAlphaPremultipliedFirst | + kCGBitmapByteOrder32Host); + + // Change the coordinate system to match WebCore's + CGContextTranslateCTM(context, 0, height); + CGContextScaleCTM(context, 1.0, -1.0); + CGColorSpaceRelease(color_space); + } // The device object will take ownership of the graphics context. return new BitmapPlatformDeviceMac( - new BitmapPlatformDeviceMacData(bitmap_context), bitmap); + new BitmapPlatformDeviceMacData(context), bitmap); } // The device will own the bitmap, which corresponds to also owning the pixel diff --git a/skia/ext/platform_canvas_linux.cc b/skia/ext/platform_canvas_linux.cc index d436fd7..422693c 100644 --- a/skia/ext/platform_canvas_linux.cc +++ b/skia/ext/platform_canvas_linux.cc @@ -21,6 +21,13 @@ PlatformCanvasLinux::PlatformCanvasLinux(int width, int height, bool is_opaque) SK_CRASH(); } +PlatformCanvasLinux::PlatformCanvasLinux(int width, int height, bool is_opaque, + uint8_t* data) + : SkCanvas() { + if (!initialize(width, height, is_opaque, data)) + SK_CRASH(); +} + PlatformCanvasLinux::~PlatformCanvasLinux() { } @@ -34,6 +41,18 @@ bool PlatformCanvasLinux::initialize(int width, int height, bool is_opaque) { return true; } +bool PlatformCanvasLinux::initialize(int width, int height, bool is_opaque, + uint8_t* data) { + SkDevice* device = + BitmapPlatformDeviceLinux::Create(width, height, is_opaque, data); + if (!device) + return false; + + setDevice(device); + device->unref(); // was created with refcount 1, and setDevice also refs + return true; +} + PlatformDeviceLinux& PlatformCanvasLinux::getTopPlatformDevice() const { // All of our devices should be our special PlatformDevice. SkCanvas::LayerIter iter(const_cast<PlatformCanvasLinux*>(this), false); diff --git a/skia/ext/platform_canvas_linux.h b/skia/ext/platform_canvas_linux.h index 5782284..1cf87a8 100644 --- a/skia/ext/platform_canvas_linux.h +++ b/skia/ext/platform_canvas_linux.h @@ -30,6 +30,7 @@ class PlatformCanvasLinux : public SkCanvas { // For two-part init, call if you use the no-argument constructor above bool initialize(int width, int height, bool is_opaque); + bool initialize(int width, int height, bool is_opaque, uint8_t* data); // Returns the platform device pointer of the topmost rect with a non-empty // clip. Both the windows and mac versions have an equivalent of this method; diff --git a/skia/ext/platform_canvas_mac.cc b/skia/ext/platform_canvas_mac.cc index 380a78b..9ada02d 100755 --- a/skia/ext/platform_canvas_mac.cc +++ b/skia/ext/platform_canvas_mac.cc @@ -25,6 +25,14 @@ PlatformCanvasMac::PlatformCanvasMac(int width, initialize(width, height, is_opaque); } +PlatformCanvasMac::PlatformCanvasMac(int width, + int height, + bool is_opaque, + uint8_t* data) + : SkCanvas() { + initialize(width, height, is_opaque, data); +} + PlatformCanvasMac::~PlatformCanvasMac() { } @@ -40,6 +48,33 @@ bool PlatformCanvasMac::initialize(int width, return true; } +bool PlatformCanvasMac::initialize(int width, + int height, + bool is_opaque, + uint8_t* data) { + CGContextRef context = NULL; + CGColorSpaceRef colorSpace; + + colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + context = CGBitmapContextCreate( + data, width, height, 8 /* bits per plane */, 4 * width /* stride */, + colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); + CGColorSpaceRelease(colorSpace); + if (!context) + return false; + // Change the coordinate system to match WebCore's + CGContextTranslateCTM(context, 0, height); + CGContextScaleCTM(context, 1.0, -1.0); + + SkDevice* device = createPlatformDevice(width, height, is_opaque, context); + if (!device) + return false; + + setDevice(device); + device->unref(); // was created with refcount 1, and setDevice also refs + return true; +} + CGContextRef PlatformCanvasMac::beginPlatformPaint() { return getTopPlatformDevice().GetBitmapContext(); } diff --git a/skia/ext/platform_canvas_mac.h b/skia/ext/platform_canvas_mac.h index da745f8..935bdc6 100755 --- a/skia/ext/platform_canvas_mac.h +++ b/skia/ext/platform_canvas_mac.h @@ -25,10 +25,13 @@ class PlatformCanvasMac : public SkCanvas { PlatformCanvasMac(int width, int height, bool is_opaque); PlatformCanvasMac(int width, int height, bool is_opaque, CGContextRef context); + PlatformCanvasMac(int width, int height, bool is_opaque, + uint8_t* context); virtual ~PlatformCanvasMac(); // For two-part init, call if you use the no-argument constructor above bool initialize(int width, int height, bool is_opaque); + bool initialize(int width, int height, bool is_opaque, uint8_t* data); // These calls should surround calls to platform drawing routines. The CG // context returned by beginPlatformPaint is the one that can be used to |