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

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

Issue 44253005: 2D Canvas: Refactor code re-attempting to allocate an imageBuffer. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@convertL
Patch Set: Merge with CL 74533004 to test on win and mac. Created 7 years, 1 month 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
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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 67
68 HTMLCanvasElement::HTMLCanvasElement(Document& document) 68 HTMLCanvasElement::HTMLCanvasElement(Document& document)
69 : HTMLElement(canvasTag, document) 69 : HTMLElement(canvasTag, document)
70 , m_size(DefaultWidth, DefaultHeight) 70 , m_size(DefaultWidth, DefaultHeight)
71 , m_rendererIsCanvas(false) 71 , m_rendererIsCanvas(false)
72 , m_ignoreReset(false) 72 , m_ignoreReset(false)
73 , m_accelerationDisabled(false) 73 , m_accelerationDisabled(false)
74 , m_externallyAllocatedMemory(0) 74 , m_externallyAllocatedMemory(0)
75 , m_deviceScaleFactor(1) 75 , m_deviceScaleFactor(1)
76 , m_originClean(true) 76 , m_originClean(true)
77 , m_hasCreatedImageBuffer(false) 77 , m_didFailToCreateImageBuffer(false)
78 , m_didClearImageBuffer(false) 78 , m_didClearImageBuffer(false)
79 { 79 {
80 ScriptWrappable::init(this); 80 ScriptWrappable::init(this);
81 } 81 }
82 82
83 PassRefPtr<HTMLCanvasElement> HTMLCanvasElement::create(Document& document) 83 PassRefPtr<HTMLCanvasElement> HTMLCanvasElement::create(Document& document)
84 { 84 {
85 return adoptRef(new HTMLCanvasElement(document)); 85 return adoptRef(new HTMLCanvasElement(document));
86 } 86 }
87 87
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) 224 for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it)
225 (*it)->canvasChanged(this, rect); 225 (*it)->canvasChanged(this, rect);
226 } 226 }
227 227
228 void HTMLCanvasElement::reset() 228 void HTMLCanvasElement::reset()
229 { 229 {
230 if (m_ignoreReset) 230 if (m_ignoreReset)
231 return; 231 return;
232 232
233 bool ok; 233 bool ok;
234 bool hadImageBuffer = hasCreatedImageBuffer(); 234 bool hadImageBuffer = hasImageBuffer();
235 235
236 int w = getAttribute(widthAttr).toInt(&ok); 236 int w = getAttribute(widthAttr).toInt(&ok);
237 if (!ok || w < 0) 237 if (!ok || w < 0)
238 w = DefaultWidth; 238 w = DefaultWidth;
239 239
240 int h = getAttribute(heightAttr).toInt(&ok); 240 int h = getAttribute(heightAttr).toInt(&ok);
241 if (!ok || h < 0) 241 if (!ok || h < 0)
242 h = DefaultHeight; 242 h = DefaultHeight;
243 243
244 if (m_contextStateSaver) { 244 if (m_contextStateSaver) {
245 // Reset to the initial graphics context state. 245 // Reset to the initial graphics context state.
246 m_contextStateSaver->restore(); 246 m_contextStateSaver->restore();
247 m_contextStateSaver->save(); 247 m_contextStateSaver->save();
248 } 248 }
249 249
250 if (m_context && m_context->is2d()) { 250 if (m_context && m_context->is2d()) {
251 CanvasRenderingContext2D* context2D = static_cast<CanvasRenderingContext 2D*>(m_context.get()); 251 CanvasRenderingContext2D* context2D = static_cast<CanvasRenderingContext 2D*>(m_context.get());
252 context2D->reset(); 252 context2D->reset();
253 } 253 }
254 254
255 IntSize oldSize = size(); 255 IntSize oldSize = size();
256 IntSize newSize(w, h); 256 IntSize newSize(w, h);
257 float newDeviceScaleFactor = 1; 257 float newDeviceScaleFactor = 1;
258 258
259 // If the size of an existing buffer matches, we can just clear it instead o f reallocating. 259 // If the size of an existing buffer matches, we can just clear it instead o f reallocating.
260 // This optimization is only done for 2D canvases for now. 260 // This optimization is only done for 2D canvases for now.
261 if (m_hasCreatedImageBuffer && oldSize == newSize && m_deviceScaleFactor == newDeviceScaleFactor && m_context && m_context->is2d()) { 261 if (hadImageBuffer && oldSize == newSize && m_deviceScaleFactor == newDevice ScaleFactor && m_context && m_context->is2d()) {
262 if (!m_didClearImageBuffer) 262 if (!m_didClearImageBuffer)
263 clearImageBuffer(); 263 clearImageBuffer();
264 return; 264 return;
265 } 265 }
266 266
267 m_deviceScaleFactor = newDeviceScaleFactor; 267 m_deviceScaleFactor = newDeviceScaleFactor;
268 268
269 setSurfaceSize(newSize); 269 setSurfaceSize(newSize);
270 270
271 if (m_context && m_context->is3d() && oldSize != size()) 271 if (m_context && m_context->is3d() && oldSize != size())
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 309
310 if (context->paintingDisabled()) 310 if (context->paintingDisabled())
311 return; 311 return;
312 312
313 if (m_context) { 313 if (m_context) {
314 if (!paintsIntoCanvasBuffer() && !document().printing()) 314 if (!paintsIntoCanvasBuffer() && !document().printing())
315 return; 315 return;
316 m_context->paintRenderingResultsToCanvas(); 316 m_context->paintRenderingResultsToCanvas();
317 } 317 }
318 318
319 if (hasCreatedImageBuffer()) { 319 if (hasImageBuffer()) {
320 ImageBuffer* imageBuffer = buffer(); 320 ImageBuffer* imageBuffer = buffer();
321 if (imageBuffer) { 321 if (imageBuffer) {
322 CompositeOperator compositeOperator = !m_context || m_context->hasAl pha() ? CompositeSourceOver : CompositeCopy; 322 CompositeOperator compositeOperator = !m_context || m_context->hasAl pha() ? CompositeSourceOver : CompositeCopy;
323 if (m_presentedImage) 323 if (m_presentedImage)
324 context->drawImage(m_presentedImage.get(), pixelSnappedIntRect(r ), compositeOperator, DoNotRespectImageOrientation, useLowQualityScale); 324 context->drawImage(m_presentedImage.get(), pixelSnappedIntRect(r ), compositeOperator, DoNotRespectImageOrientation, useLowQualityScale);
325 else 325 else
326 context->drawImageBuffer(imageBuffer, pixelSnappedIntRect(r), co mpositeOperator, BlendModeNormal, useLowQualityScale); 326 context->drawImageBuffer(imageBuffer, pixelSnappedIntRect(r), co mpositeOperator, BlendModeNormal, useLowQualityScale);
327 } 327 }
328 } 328 }
329 329
(...skipping 15 matching lines...) Expand all
345 } 345 }
346 346
347 void HTMLCanvasElement::clearPresentationCopy() 347 void HTMLCanvasElement::clearPresentationCopy()
348 { 348 {
349 m_presentedImage.clear(); 349 m_presentedImage.clear();
350 } 350 }
351 351
352 void HTMLCanvasElement::setSurfaceSize(const IntSize& size) 352 void HTMLCanvasElement::setSurfaceSize(const IntSize& size)
353 { 353 {
354 m_size = size; 354 m_size = size;
355 m_hasCreatedImageBuffer = false; 355 m_didFailToCreateImageBuffer = false;
356 m_contextStateSaver.clear(); 356 m_contextStateSaver.clear();
357 m_imageBuffer.clear(); 357 m_imageBuffer.clear();
358 setExternallyAllocatedMemory(0); 358 setExternallyAllocatedMemory(0);
359 clearCopiedImage(); 359 clearCopiedImage();
360 } 360 }
361 361
362 String HTMLCanvasElement::toEncodingMimeType(const String& mimeType) 362 String HTMLCanvasElement::toEncodingMimeType(const String& mimeType)
363 { 363 {
364 String lowercaseMimeType = mimeType.lower(); 364 String lowercaseMimeType = mimeType.lower();
365 365
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 if (!m_context || !m_context->is3d()) 399 if (!m_context || !m_context->is3d())
400 return 0; 400 return 0;
401 401
402 WebGLRenderingContext* ctx = static_cast<WebGLRenderingContext*>(m_context.g et()); 402 WebGLRenderingContext* ctx = static_cast<WebGLRenderingContext*>(m_context.g et());
403 403
404 return ctx->paintRenderingResultsToImageData(); 404 return ctx->paintRenderingResultsToImageData();
405 } 405 }
406 406
407 IntSize HTMLCanvasElement::convertLogicalToDevice(const IntSize& logicalSize) co nst 407 IntSize HTMLCanvasElement::convertLogicalToDevice(const IntSize& logicalSize) co nst
408 { 408 {
409 float width = ceilf(logicalSize.width() * m_deviceScaleFactor); 409 FloatSize deviceSize = logicalSize * m_deviceScaleFactor;
410 float height = ceilf(logicalSize.height() * m_deviceScaleFactor); 410 return expandedIntSize(deviceSize);
411 return IntSize(width, height);
412 } 411 }
413 412
414 SecurityOrigin* HTMLCanvasElement::securityOrigin() const 413 SecurityOrigin* HTMLCanvasElement::securityOrigin() const
415 { 414 {
416 return document().securityOrigin(); 415 return document().securityOrigin();
417 } 416 }
418 417
419 StyleResolver* HTMLCanvasElement::styleResolver() 418 StyleResolver* HTMLCanvasElement::styleResolver()
420 { 419 {
421 return document().styleResolver(); 420 return document().styleResolver();
(...skipping 18 matching lines...) Expand all
440 if (!blink::Platform::current()->canAccelerate2dCanvas()) 439 if (!blink::Platform::current()->canAccelerate2dCanvas())
441 return false; 440 return false;
442 441
443 return true; 442 return true;
444 } 443 }
445 444
446 void HTMLCanvasElement::createImageBuffer() 445 void HTMLCanvasElement::createImageBuffer()
447 { 446 {
448 ASSERT(!m_imageBuffer); 447 ASSERT(!m_imageBuffer);
449 448
450 m_hasCreatedImageBuffer = true; 449 m_didFailToCreateImageBuffer = true;
451 m_didClearImageBuffer = true; 450 m_didClearImageBuffer = true;
452 451
453 IntSize deviceSize = convertLogicalToDevice(size()); 452 IntSize deviceSize = convertLogicalToDevice(size());
454 if (deviceSize.width() * deviceSize.height() > MaxCanvasArea) 453 if (deviceSize.width() * deviceSize.height() > MaxCanvasArea)
455 return; 454 return;
456 455
457 if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim) 456 if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim)
458 return; 457 return;
459 458
460 if (!deviceSize.width() || !deviceSize.height()) 459 if (!deviceSize.width() || !deviceSize.height())
461 return; 460 return;
462 461
463 RenderingMode renderingMode = is3D() ? TextureBacked : (shouldAccelerate(dev iceSize) ? Accelerated : UnacceleratedNonPlatformBuffer); 462 RenderingMode renderingMode = is3D() ? TextureBacked : (shouldAccelerate(dev iceSize) ? Accelerated : UnacceleratedNonPlatformBuffer);
464 int msaaSampleCount = 0; 463 int msaaSampleCount = 0;
465 if (document().settings()) 464 if (document().settings())
466 msaaSampleCount = document().settings()->accelerated2dCanvasMSAASampleCo unt(); 465 msaaSampleCount = document().settings()->accelerated2dCanvasMSAASampleCo unt();
467 OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque : Opaque; 466 OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque : Opaque;
468 m_imageBuffer = ImageBuffer::create(size(), m_deviceScaleFactor, renderingMo de, opacityMode, msaaSampleCount); 467 m_imageBuffer = ImageBuffer::create(size(), m_deviceScaleFactor, renderingMo de, opacityMode, msaaSampleCount);
469 if (!m_imageBuffer) 468 if (!m_imageBuffer)
470 return; 469 return;
470 m_didFailToCreateImageBuffer = false;
471 setExternallyAllocatedMemory(4 * width() * height()); 471 setExternallyAllocatedMemory(4 * width() * height());
472 m_imageBuffer->context()->setShouldClampToSourceRect(false); 472 m_imageBuffer->context()->setShouldClampToSourceRect(false);
473 m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQ uality); 473 m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQ uality);
474 // Enabling MSAA overrides a request to disable antialiasing. This is true r egardless of whether the 474 // Enabling MSAA overrides a request to disable antialiasing. This is true r egardless of whether the
475 // rendering mode is accelerated or not. For consistency, we don't want to a pply AA in accelerated 475 // rendering mode is accelerated or not. For consistency, we don't want to a pply AA in accelerated
476 // canvases but not in unaccelerated canvases. 476 // canvases but not in unaccelerated canvases.
477 if (!msaaSampleCount && document().settings() && !document().settings()->ant ialiased2dCanvasEnabled()) 477 if (!msaaSampleCount && document().settings() && !document().settings()->ant ialiased2dCanvasEnabled())
478 m_imageBuffer->context()->setShouldAntialias(false); 478 m_imageBuffer->context()->setShouldAntialias(false);
479 // GraphicsContext's defaults don't always agree with the 2d canvas spec. 479 // GraphicsContext's defaults don't always agree with the 2d canvas spec.
480 // See CanvasRenderingContext2D::State::State() for more information. 480 // See CanvasRenderingContext2D::State::State() for more information.
(...skipping 12 matching lines...) Expand all
493 m_externallyAllocatedMemory = externallyAllocatedMemory; 493 m_externallyAllocatedMemory = externallyAllocatedMemory;
494 } 494 }
495 495
496 GraphicsContext* HTMLCanvasElement::drawingContext() const 496 GraphicsContext* HTMLCanvasElement::drawingContext() const
497 { 497 {
498 return buffer() ? m_imageBuffer->context() : 0; 498 return buffer() ? m_imageBuffer->context() : 0;
499 } 499 }
500 500
501 GraphicsContext* HTMLCanvasElement::existingDrawingContext() const 501 GraphicsContext* HTMLCanvasElement::existingDrawingContext() const
502 { 502 {
503 if (!m_hasCreatedImageBuffer) 503 if (m_didFailToCreateImageBuffer) {
504 ASSERT(!hasImageBuffer());
504 return 0; 505 return 0;
506 }
505 507
506 return drawingContext(); 508 return drawingContext();
507 } 509 }
508 510
509 ImageBuffer* HTMLCanvasElement::buffer() const 511 ImageBuffer* HTMLCanvasElement::buffer() const
510 { 512 {
511 if (!m_hasCreatedImageBuffer) 513 if (!hasImageBuffer() && !m_didFailToCreateImageBuffer)
512 const_cast<HTMLCanvasElement*>(this)->createImageBuffer(); 514 const_cast<HTMLCanvasElement*>(this)->createImageBuffer();
513 return m_imageBuffer.get(); 515 return m_imageBuffer.get();
514 } 516 }
515 517
516 Image* HTMLCanvasElement::copiedImage() const 518 Image* HTMLCanvasElement::copiedImage() const
517 { 519 {
518 if (!m_copiedImage && buffer()) { 520 if (!m_copiedImage && buffer()) {
519 if (m_context) 521 if (m_context)
520 m_context->paintRenderingResultsToCanvas(); 522 m_context->paintRenderingResultsToCanvas();
521 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); 523 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled);
522 } 524 }
523 return m_copiedImage.get(); 525 return m_copiedImage.get();
524 } 526 }
525 527
526 void HTMLCanvasElement::clearImageBuffer() 528 void HTMLCanvasElement::clearImageBuffer()
527 { 529 {
528 ASSERT(m_hasCreatedImageBuffer); 530 ASSERT(hasImageBuffer() && !m_didFailToCreateImageBuffer);
529 ASSERT(!m_didClearImageBuffer); 531 ASSERT(!m_didClearImageBuffer);
530 ASSERT(m_context); 532 ASSERT(m_context);
531 533
532 m_didClearImageBuffer = true; 534 m_didClearImageBuffer = true;
533 535
534 if (m_context->is2d()) { 536 if (m_context->is2d()) {
535 CanvasRenderingContext2D* context2D = static_cast<CanvasRenderingContext 2D*>(m_context.get()); 537 CanvasRenderingContext2D* context2D = static_cast<CanvasRenderingContext 2D*>(m_context.get());
536 // No need to undo transforms/clip/etc. because we are called right afte r the context is reset. 538 // No need to undo transforms/clip/etc. because we are called right afte r the context is reset.
537 context2D->clearRect(0, 0, width(), height()); 539 context2D->clearRect(0, 0, width(), height());
538 } 540 }
539 } 541 }
540 542
541 void HTMLCanvasElement::clearCopiedImage() 543 void HTMLCanvasElement::clearCopiedImage()
542 { 544 {
543 m_copiedImage.clear(); 545 m_copiedImage.clear();
544 m_didClearImageBuffer = false; 546 m_didClearImageBuffer = false;
545 } 547 }
546 548
547 AffineTransform HTMLCanvasElement::baseTransform() const 549 AffineTransform HTMLCanvasElement::baseTransform() const
548 { 550 {
549 ASSERT(m_hasCreatedImageBuffer); 551 ASSERT(hasImageBuffer() && !m_didFailToCreateImageBuffer);
550 IntSize unscaledSize = size(); 552 IntSize unscaledSize = size();
551 IntSize size = convertLogicalToDevice(unscaledSize); 553 IntSize size = convertLogicalToDevice(unscaledSize);
552 AffineTransform transform; 554 AffineTransform transform;
553 if (size.width() && size.height()) 555 if (size.width() && size.height())
554 transform.scaleNonUniform(size.width() / unscaledSize.width(), size.heig ht() / unscaledSize.height()); 556 transform.scaleNonUniform(size.width() / unscaledSize.width(), size.heig ht() / unscaledSize.height());
555 return m_imageBuffer->baseTransform() * transform; 557 return m_imageBuffer->baseTransform() * transform;
556 } 558 }
557 559
558 } 560 }
OLDNEW
« no previous file with comments | « Source/core/html/HTMLCanvasElement.h ('k') | Source/core/html/canvas/CanvasRenderingContext2D.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698