Chromium Code Reviews| Index: webkit/api/src/GraphicsContext3D.cpp |
| =================================================================== |
| --- webkit/api/src/GraphicsContext3D.cpp (revision 30753) |
| +++ webkit/api/src/GraphicsContext3D.cpp (working copy) |
| @@ -163,6 +163,15 @@ |
| }; |
| VertexAttribPointerState m_vertexAttribPointerState[NumTrackedPointerStates]; |
| +#if PLATFORM(SKIA) |
| + // If the width and height of the Canvas's backing store don't |
| + // match those that we were given in the most recent call to |
| + // reshape(), then we need an intermediate bitmap to read back the |
| + // frame buffer into. This seems to happen when CSS styles are |
| + // used to resize the Canvas. |
| + SkBitmap* m_resizingBitmap; |
| +#endif |
| + |
| #if PLATFORM(WIN_OS) |
| HWND m_canvasWindow; |
| HDC m_canvasDC; |
| @@ -224,6 +233,9 @@ |
| , m_scanline(NULL) |
| #endif |
| , m_boundArrayBuffer(0) |
| +#if PLATFORM(SKIA) |
| + , m_resizingBitmap(0) |
| +#endif |
| #if PLATFORM(WIN_OS) |
| , m_canvasWindow(NULL) |
| , m_canvasDC(NULL) |
| @@ -475,6 +487,10 @@ |
| #endif |
| glDeleteFramebuffersEXT(1, &m_fbo); |
| #endif // !RENDER_TO_DEBUGGING_WINDOW |
| +#if PLATFORM(SKIA) |
| + if (m_resizingBitmap) |
| + delete m_resizingBitmap; |
| +#endif |
| #if PLATFORM(WIN_OS) |
| wglMakeCurrent(NULL, NULL); |
| wglDeleteContext(m_contextObj); |
| @@ -672,16 +688,47 @@ |
| HTMLCanvasElement* canvas = context->canvas(); |
| ImageBuffer* imageBuffer = canvas->buffer(); |
| - unsigned char* pixels = NULL; |
| + unsigned char* pixels = 0; |
| #if PLATFORM(SKIA) |
| - const SkBitmap& bitmap = *imageBuffer->context()->platformContext()->bitmap(); |
| - ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); |
| - ASSERT(bitmap.width() == m_cachedWidth); |
| - ASSERT(bitmap.height() == m_cachedHeight); |
| + const SkBitmap* canvasBitmap = imageBuffer->context()->platformContext()->bitmap(); |
| + const SkBitmap* readbackBitmap = 0; |
| + ASSERT(canvasBitmap->config() == SkBitmap::kARGB_8888_Config); |
| + if (canvasBitmap->width() == m_cachedWidth && |
| + canvasBitmap->height() == m_cachedHeight) { |
| + // This is the fastest and most common case. We read back |
| + // directly into the canvas's backing store. |
| + readbackBitmap = canvasBitmap; |
| + if (m_resizingBitmap != NULL) { |
| + delete m_resizingBitmap; |
| + m_resizingBitmap = 0; |
| + } |
| + } else { |
| + // We need to allocate a temporary bitmap for reading back the |
| + // pixel data. We will then use Skia to rescale this bitmap to |
| + // the size of the canvas's backing store. |
| + if (m_resizingBitmap && |
| + (m_resizingBitmap->width() != m_cachedWidth || |
| + m_resizingBitmap->height() != m_cachedHeight)) { |
| + delete m_resizingBitmap; |
| + m_resizingBitmap = 0; |
| + } |
| + if (m_resizingBitmap == 0) { |
| + m_resizingBitmap = new SkBitmap(); |
| + m_resizingBitmap->setConfig(SkBitmap::kARGB_8888_Config, |
| + m_cachedWidth, |
| + m_cachedHeight); |
| + if (!m_resizingBitmap->allocPixels()) { |
| + delete m_resizingBitmap; |
| + m_resizingBitmap = 0; |
| + return; |
| + } |
| + } |
| + readbackBitmap = m_resizingBitmap; |
| + } |
| // Read back the frame buffer. |
| - SkAutoLockPixels bitmapLock(bitmap); |
| - pixels = static_cast<unsigned char*>(bitmap.getPixels()); |
| + SkAutoLockPixels bitmapLock(*readbackBitmap); |
| + pixels = static_cast<unsigned char*>(readbackBitmap->getPixels()); |
| glReadPixels(0, 0, m_cachedWidth, m_cachedHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels); |
| #elif PLATFORM(CG) |
| if (m_renderOutput != NULL) { |
| @@ -700,11 +747,22 @@ |
| #endif |
| #if PLATFORM(SKIA) |
| - // No further work necessary |
| + if (m_resizingBitmap) { |
| + // We need to draw the resizing bitmap into the canvas's backing store. |
| + SkCanvas canvas(*canvasBitmap); |
| + SkRect dst; |
| + dst.set(0, 0, canvasBitmap->width(), canvasBitmap->height()); |
| + canvas.drawBitmapRect(*m_resizingBitmap, 0, dst); |
|
brettw
2009/11/03 20:21:18
Do you want antialiasing? This call will not give
|
| + } |
| #elif PLATFORM(CG) |
| if (m_renderOutput != NULL) { |
| CGImageRef cgImage = CGBitmapContextCreateImage(m_cgContext); |
| - CGRect rect = CGRectMake(0, 0, m_cachedWidth, m_cachedHeight); |
| + // CSS styling may cause the canvas's content to be resized on |
| + // the page. Go back to the Canvas to figure out the correct |
| + // width and height to draw. |
| + CGRect rect = CGRectMake(0, 0, |
| + context->canvas()->width(), |
| + context->canvas()->height()); |
| // We want to completely overwrite the previous frame's |
| // rendering results. |
| CGContextSetBlendMode(imageBuffer->context()->platformContext(), |