Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(713)

Side by Side Diff: Source/core/html/HTMLCanvasElement.cpp

Issue 104023007: Refactoring ImageBuffer to decouple it from Canvas2DLayerBridge (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: mac+win build fix Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 27 matching lines...) Expand all
38 #include "core/dom/ExceptionCode.h" 38 #include "core/dom/ExceptionCode.h"
39 #include "core/html/ImageData.h" 39 #include "core/html/ImageData.h"
40 #include "core/html/canvas/Canvas2DContextAttributes.h" 40 #include "core/html/canvas/Canvas2DContextAttributes.h"
41 #include "core/html/canvas/CanvasRenderingContext2D.h" 41 #include "core/html/canvas/CanvasRenderingContext2D.h"
42 #include "core/html/canvas/WebGLContextAttributes.h" 42 #include "core/html/canvas/WebGLContextAttributes.h"
43 #include "core/html/canvas/WebGLRenderingContext.h" 43 #include "core/html/canvas/WebGLRenderingContext.h"
44 #include "core/frame/Frame.h" 44 #include "core/frame/Frame.h"
45 #include "core/page/Settings.h" 45 #include "core/page/Settings.h"
46 #include "core/rendering/RenderHTMLCanvas.h" 46 #include "core/rendering/RenderHTMLCanvas.h"
47 #include "platform/MIMETypeRegistry.h" 47 #include "platform/MIMETypeRegistry.h"
48 #include "platform/graphics/Canvas2DImageBufferSurface.h"
48 #include "platform/graphics/GraphicsContextStateSaver.h" 49 #include "platform/graphics/GraphicsContextStateSaver.h"
49 #include "platform/graphics/ImageBuffer.h" 50 #include "platform/graphics/ImageBuffer.h"
51 #include "platform/graphics/UnacceleratedImageBufferSurface.h"
52 #include "platform/graphics/gpu/WebGLImageBufferSurface.h"
50 #include "public/platform/Platform.h" 53 #include "public/platform/Platform.h"
51 54
52 namespace WebCore { 55 namespace WebCore {
53 56
54 using namespace HTMLNames; 57 using namespace HTMLNames;
55 58
56 // These values come from the WhatWG spec. 59 // These values come from the WhatWG spec.
57 static const int DefaultWidth = 300; 60 static const int DefaultWidth = 300;
58 static const int DefaultHeight = 150; 61 static const int DefaultHeight = 150;
59 62
60 // Firefox limits width/height to 32767 pixels, but slows down dramatically befo re it 63 // Firefox limits width/height to 32767 pixels, but slows down dramatically befo re it
61 // reaches that limit. We limit by area instead, giving us larger maximum dimens ions, 64 // reaches that limit. We limit by area instead, giving us larger maximum dimens ions,
62 // in exchange for a smaller maximum canvas size. 65 // in exchange for a smaller maximum canvas size.
63 static const int MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pix els 66 static const int MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pix els
64 67
65 //In Skia, we will also limit width/height to 32767. 68 //In Skia, we will also limit width/height to 32767.
66 static const int MaxSkiaDim = 32767; // Maximum width/height in CSS pixels. 69 static const int MaxSkiaDim = 32767; // Maximum width/height in CSS pixels.
67 70
68 HTMLCanvasElement::HTMLCanvasElement(Document& document) 71 HTMLCanvasElement::HTMLCanvasElement(Document& document)
69 : HTMLElement(canvasTag, document) 72 : HTMLElement(canvasTag, document)
70 , m_size(DefaultWidth, DefaultHeight) 73 , m_size(DefaultWidth, DefaultHeight)
71 , m_rendererIsCanvas(false) 74 , m_rendererIsCanvas(false)
72 , m_ignoreReset(false) 75 , m_ignoreReset(false)
73 , m_accelerationDisabled(false) 76 , m_accelerationDisabled(false)
74 , m_externallyAllocatedMemory(0) 77 , m_externallyAllocatedMemory(0)
75 , m_deviceScaleFactor(1)
76 , m_originClean(true) 78 , m_originClean(true)
77 , m_didFailToCreateImageBuffer(false) 79 , m_didFailToCreateImageBuffer(false)
78 , m_didClearImageBuffer(false) 80 , m_didClearImageBuffer(false)
79 { 81 {
80 ScriptWrappable::init(this); 82 ScriptWrappable::init(this);
81 } 83 }
82 84
83 PassRefPtr<HTMLCanvasElement> HTMLCanvasElement::create(Document& document) 85 PassRefPtr<HTMLCanvasElement> HTMLCanvasElement::create(Document& document)
84 { 86 {
85 return adoptRef(new HTMLCanvasElement(document)); 87 return adoptRef(new HTMLCanvasElement(document));
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 // Reset to the initial graphics context state. 247 // Reset to the initial graphics context state.
246 m_contextStateSaver->restore(); 248 m_contextStateSaver->restore();
247 m_contextStateSaver->save(); 249 m_contextStateSaver->save();
248 } 250 }
249 251
250 if (m_context && m_context->is2d()) 252 if (m_context && m_context->is2d())
251 toCanvasRenderingContext2D(m_context.get())->reset(); 253 toCanvasRenderingContext2D(m_context.get())->reset();
252 254
253 IntSize oldSize = size(); 255 IntSize oldSize = size();
254 IntSize newSize(w, h); 256 IntSize newSize(w, h);
255 float newDeviceScaleFactor = 1;
256 257
257 // If the size of an existing buffer matches, we can just clear it instead o f reallocating. 258 // If the size of an existing buffer matches, we can just clear it instead o f reallocating.
258 // This optimization is only done for 2D canvases for now. 259 // This optimization is only done for 2D canvases for now.
259 if (hadImageBuffer && oldSize == newSize && m_deviceScaleFactor == newDevice ScaleFactor && m_context && m_context->is2d()) { 260 if (hadImageBuffer && oldSize == newSize && m_context && m_context->is2d()) {
260 if (!m_didClearImageBuffer) 261 if (!m_didClearImageBuffer)
261 clearImageBuffer(); 262 clearImageBuffer();
262 return; 263 return;
263 } 264 }
264 265
265 m_deviceScaleFactor = newDeviceScaleFactor;
266
267 setSurfaceSize(newSize); 266 setSurfaceSize(newSize);
268 267
269 if (m_context && m_context->is3d() && oldSize != size()) 268 if (m_context && m_context->is3d() && oldSize != size())
270 toWebGLRenderingContext(m_context.get())->reshape(width(), height()); 269 toWebGLRenderingContext(m_context.get())->reshape(width(), height());
271 270
272 if (RenderObject* renderer = this->renderer()) { 271 if (RenderObject* renderer = this->renderer()) {
273 if (m_rendererIsCanvas) { 272 if (m_rendererIsCanvas) {
274 if (oldSize != size()) { 273 if (oldSize != size()) {
275 toRenderHTMLCanvas(renderer)->canvasSizeChanged(); 274 toRenderHTMLCanvas(renderer)->canvasSizeChanged();
276 if (renderBox() && renderBox()->hasAcceleratedCompositing()) 275 if (renderBox() && renderBox()->hasAcceleratedCompositing())
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 return buffer()->toDataURL(encodingMimeType, quality); 391 return buffer()->toDataURL(encodingMimeType, quality);
393 } 392 }
394 393
395 PassRefPtr<ImageData> HTMLCanvasElement::getImageData() 394 PassRefPtr<ImageData> HTMLCanvasElement::getImageData()
396 { 395 {
397 if (!m_context || !m_context->is3d()) 396 if (!m_context || !m_context->is3d())
398 return 0; 397 return 0;
399 return toWebGLRenderingContext(m_context.get())->paintRenderingResultsToImag eData(); 398 return toWebGLRenderingContext(m_context.get())->paintRenderingResultsToImag eData();
400 } 399 }
401 400
402 IntSize HTMLCanvasElement::convertLogicalToDevice(const IntSize& logicalSize) co nst
403 {
404 FloatSize deviceSize = logicalSize * m_deviceScaleFactor;
405 return expandedIntSize(deviceSize);
406 }
407
408 SecurityOrigin* HTMLCanvasElement::securityOrigin() const 401 SecurityOrigin* HTMLCanvasElement::securityOrigin() const
409 { 402 {
410 return document().securityOrigin(); 403 return document().securityOrigin();
411 } 404 }
412 405
413 bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const 406 bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const
414 { 407 {
415 if (m_context && !m_context->is2d()) 408 if (m_context && !m_context->is2d())
416 return false; 409 return false;
417 410
418 if (m_accelerationDisabled) 411 if (m_accelerationDisabled)
419 return false; 412 return false;
420 413
421 Settings* settings = document().settings(); 414 Settings* settings = document().settings();
422 if (!settings || !settings->accelerated2dCanvasEnabled()) 415 if (!settings || !settings->accelerated2dCanvasEnabled())
423 return false; 416 return false;
424 417
425 // Do not use acceleration for small canvas. 418 // Do not use acceleration for small canvas.
426 if (size.width() * size.height() < settings->minimumAccelerated2dCanvasSize( )) 419 if (size.width() * size.height() < settings->minimumAccelerated2dCanvasSize( ))
427 return false; 420 return false;
428 421
429 if (!blink::Platform::current()->canAccelerate2dCanvas()) 422 if (!blink::Platform::current()->canAccelerate2dCanvas())
430 return false; 423 return false;
431 424
432 return true; 425 return true;
433 } 426 }
434 427
428 PassOwnPtr<ImageBufferSurface> HTMLCanvasElement::createImageBufferSurface(const IntSize& deviceSize, int* msaaSampleCount)
429 {
430 OwnPtr<ImageBufferSurface> surface;
431 OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque : Opaque;
432 *msaaSampleCount = 0;
433 if (is3D()) {
434 surface = adoptPtr(new WebGLImageBufferSurface(size(), opacityMode));
Stephen White 2013/12/09 15:33:08 Nit: I'd just do an early-return here, to save ind
435 } else {
436 if (shouldAccelerate(deviceSize)) {
437 if (document().settings())
438 *msaaSampleCount = document().settings()->accelerated2dCanvasMSA ASampleCount();
439 surface = adoptPtr(new Canvas2DImageBufferSurface(size(), opacityMod e, *msaaSampleCount));
440 }
441
442 if (!surface || !surface->isValid()) {
443 surface = adoptPtr(new UnacceleratedImageBufferSurface(size(), opaci tyMode));
444 }
445 }
446
447 return surface.release();
448 }
449
435 void HTMLCanvasElement::createImageBuffer() 450 void HTMLCanvasElement::createImageBuffer()
436 { 451 {
437 ASSERT(!m_imageBuffer); 452 ASSERT(!m_imageBuffer);
438 453
439 m_didFailToCreateImageBuffer = true; 454 m_didFailToCreateImageBuffer = true;
440 m_didClearImageBuffer = true; 455 m_didClearImageBuffer = true;
441 456
442 IntSize deviceSize = convertLogicalToDevice(size()); 457 IntSize deviceSize = size();
443 if (deviceSize.width() * deviceSize.height() > MaxCanvasArea) 458 if (deviceSize.width() * deviceSize.height() > MaxCanvasArea)
444 return; 459 return;
445 460
446 if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim) 461 if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim)
447 return; 462 return;
448 463
449 if (!deviceSize.width() || !deviceSize.height()) 464 if (!deviceSize.width() || !deviceSize.height())
450 return; 465 return;
451 466
452 RenderingMode renderingMode = is3D() ? TextureBacked : (shouldAccelerate(dev iceSize) ? Accelerated : UnacceleratedNonPlatformBuffer); 467 int msaaSampleCount;
453 int msaaSampleCount = 0; 468 OwnPtr<ImageBufferSurface> surface = createImageBufferSurface(deviceSize, &m saaSampleCount);
Stephen White 2013/12/09 15:33:08 Do we need to check for a NULL surface here? If it
Justin Novosad 2013/12/09 16:37:31 It was caught bey the check below, but I'll move t
454 if (document().settings()) 469 m_imageBuffer = ImageBuffer::create(surface.release());
455 msaaSampleCount = document().settings()->accelerated2dCanvasMSAASampleCo unt();
456 OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque : Opaque;
457 m_imageBuffer = ImageBuffer::create(size(), m_deviceScaleFactor, renderingMo de, opacityMode, msaaSampleCount);
458 if (!m_imageBuffer) 470 if (!m_imageBuffer)
459 return; 471 return;
472
460 m_didFailToCreateImageBuffer = false; 473 m_didFailToCreateImageBuffer = false;
474
461 setExternallyAllocatedMemory(4 * width() * height()); 475 setExternallyAllocatedMemory(4 * width() * height());
462 m_imageBuffer->context()->setShouldClampToSourceRect(false); 476
463 m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQ uality); 477 if (m_imageBuffer->context()) {
Stephen White 2013/12/09 15:33:08 Under what conditions does the image buffer have n
464 // Enabling MSAA overrides a request to disable antialiasing. This is true r egardless of whether the 478 m_imageBuffer->context()->setShouldClampToSourceRect(false);
465 // rendering mode is accelerated or not. For consistency, we don't want to a pply AA in accelerated 479 m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolat ionQuality);
466 // canvases but not in unaccelerated canvases. 480 // Enabling MSAA overrides a request to disable antialiasing. This is tr ue regardless of whether the
467 if (!msaaSampleCount && document().settings() && !document().settings()->ant ialiased2dCanvasEnabled()) 481 // rendering mode is accelerated or not. For consistency, we don't want to apply AA in accelerated
468 m_imageBuffer->context()->setShouldAntialias(false); 482 // canvases but not in unaccelerated canvases.
469 // GraphicsContext's defaults don't always agree with the 2d canvas spec. 483 if (!msaaSampleCount && document().settings() && !document().settings()- >antialiased2dCanvasEnabled())
470 // See CanvasRenderingContext2D::State::State() for more information. 484 m_imageBuffer->context()->setShouldAntialias(false);
471 m_imageBuffer->context()->setMiterLimit(10); 485 // GraphicsContext's defaults don't always agree with the 2d canvas spec .
472 m_imageBuffer->context()->setStrokeThickness(1); 486 // See CanvasRenderingContext2D::State::State() for more information.
473 m_contextStateSaver = adoptPtr(new GraphicsContextStateSaver(*m_imageBuffer- >context())); 487 m_imageBuffer->context()->setMiterLimit(10);
488 m_imageBuffer->context()->setStrokeThickness(1);
489 m_contextStateSaver = adoptPtr(new GraphicsContextStateSaver(*m_imageBuf fer->context()));
490 } else {
491 m_contextStateSaver.clear();
492 }
474 493
475 // Recalculate compositing requirements if acceleration state changed. 494 // Recalculate compositing requirements if acceleration state changed.
476 if (m_context && m_context->is2d()) 495 if (m_context && m_context->is2d())
477 scheduleLayerUpdate(); 496 scheduleLayerUpdate();
478 } 497 }
479 498
480 void HTMLCanvasElement::setExternallyAllocatedMemory(intptr_t externallyAllocate dMemory) 499 void HTMLCanvasElement::setExternallyAllocatedMemory(intptr_t externallyAllocate dMemory)
481 { 500 {
482 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA llocatedMemory - m_externallyAllocatedMemory); 501 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA llocatedMemory - m_externallyAllocatedMemory);
483 m_externallyAllocatedMemory = externallyAllocatedMemory; 502 m_externallyAllocatedMemory = externallyAllocatedMemory;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 551
533 void HTMLCanvasElement::clearCopiedImage() 552 void HTMLCanvasElement::clearCopiedImage()
534 { 553 {
535 m_copiedImage.clear(); 554 m_copiedImage.clear();
536 m_didClearImageBuffer = false; 555 m_didClearImageBuffer = false;
537 } 556 }
538 557
539 AffineTransform HTMLCanvasElement::baseTransform() const 558 AffineTransform HTMLCanvasElement::baseTransform() const
540 { 559 {
541 ASSERT(hasImageBuffer() && !m_didFailToCreateImageBuffer); 560 ASSERT(hasImageBuffer() && !m_didFailToCreateImageBuffer);
542 IntSize unscaledSize = size(); 561 return m_imageBuffer->baseTransform();
543 IntSize size = convertLogicalToDevice(unscaledSize);
544 AffineTransform transform;
545 if (size.width() && size.height())
546 transform.scaleNonUniform(size.width() / unscaledSize.width(), size.heig ht() / unscaledSize.height());
547 return m_imageBuffer->baseTransform() * transform;
548 } 562 }
549 563
550 } 564 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698